Index: generic/include/ipc/ipc.h
===================================================================
--- generic/include/ipc/ipc.h	(revision ba81cab60a5926ed0eb9888e74ef22a77ec9792e)
+++ generic/include/ipc/ipc.h	(revision b4b45210fc5bef84b7f8456d96320f10dd3f5245)
@@ -38,13 +38,18 @@
 
 /* Flags for calls */
-#define IPC_CALL_ANSWERED      0x1 /**< This is answer to a call */
-#define IPC_CALL_STATIC_ALLOC  0x2 /**< This call will not be freed on error */
-#define IPC_CALL_DISPATCHED    0x4 /**< Call is in dispatch queue */
+#define IPC_CALL_ANSWERED     (1<<0) /**< This is answer to a call */
+#define IPC_CALL_STATIC_ALLOC (1<<1) /**< This call will not be freed on error */
+#define IPC_CALL_DISPATCHED   (1<<2) /**< Call is in dispatch queue */
+#define IPC_CALL_DISCARD_ANSWER (1<<3) /**< Answer will not be passed to
+					* userspace, will be discarded */
 
 /* Flags for ipc_wait_for_call */
 #define IPC_WAIT_NONBLOCKING   1
 
-/* Flags of callid */
-#define IPC_CALLID_ANSWERED  1
+/* Flags of callid (the addresses are aligned at least to 4, 
+ * that is why we can use bottom 2 bits of the call address
+ */
+#define IPC_CALLID_ANSWERED       1 /**< Type of this msg is 'answer' */
+#define IPC_CALLID_NOTIFICATION   2 /**< Type of this msg is 'notification' */
 
 /* Return values from IPC_ASYNC */
@@ -54,16 +59,16 @@
 
 /* Macros for manipulating calling data */
-#define IPC_SET_RETVAL(data, retval)   ((data)[0] = (retval))
-#define IPC_SET_METHOD(data, val)   ((data)[0] = (val))
-#define IPC_SET_ARG1(data, val)   ((data)[1] = (val))
-#define IPC_SET_ARG2(data, val)   ((data)[2] = (val))
-#define IPC_SET_ARG3(data, val)   ((data)[3] = (val))
-
-#define IPC_GET_METHOD(data)           ((data)[0])
-#define IPC_GET_RETVAL(data)           ((data)[0])
-
-#define IPC_GET_ARG1(data)              ((data)[1])
-#define IPC_GET_ARG2(data)              ((data)[2])
-#define IPC_GET_ARG3(data)              ((data)[3])
+#define IPC_SET_RETVAL(data, retval)   ((data).args[0] = (retval))
+#define IPC_SET_METHOD(data, val)   ((data).args[0] = (val))
+#define IPC_SET_ARG1(data, val)   ((data).args[1] = (val))
+#define IPC_SET_ARG2(data, val)   ((data).args[2] = (val))
+#define IPC_SET_ARG3(data, val)   ((data).args[3] = (val))
+
+#define IPC_GET_METHOD(data)           ((data).args[0])
+#define IPC_GET_RETVAL(data)           ((data).args[0])
+
+#define IPC_GET_ARG1(data)              ((data).args[1])
+#define IPC_GET_ARG2(data)              ((data).args[2])
+#define IPC_GET_ARG3(data)              ((data).args[3])
 
 /* Well known phone descriptors */
@@ -90,5 +95,5 @@
  *                     - the caller obtains taskid of the called thread
  */
-#define IPC_M_CONNECTTOME     1
+#define IPC_M_CONNECT_TO_ME     1
 /** Protocol for CONNECT - ME - TO
  *
@@ -109,8 +114,9 @@
  *
  */
-#define IPC_M_CONNECTMETO     2
-/* Control messages that the server sends to the processes 
- * about their connections.
- */
+#define IPC_M_CONNECT_ME_TO     2
+/** This message is sent to answerbox when the phone
+ * is hung up
+ */
+#define IPC_M_PHONE_HUNGUP      3
 
 
@@ -129,16 +135,12 @@
 #define IPC_MAX_PHONES  16
 
-typedef struct answerbox answerbox_t;
-typedef __native ipc_data_t[IPC_CALL_LEN];
-
+typedef struct answerbox_s answerbox_t;
+typedef struct phone_s phone_t;
 typedef struct {
-	link_t list;
-	answerbox_t *callerbox;
-	int flags;
-	task_t *sender;
-	ipc_data_t data;
-} call_t;
-
-struct answerbox {
+	__native args[IPC_CALL_LEN];
+	phone_t *phone;
+}ipc_data_t;
+
+struct answerbox_s {
 	SPINLOCK_DECLARE(lock);
 
@@ -154,10 +156,26 @@
 };
 
-typedef struct {
+struct phone_s {
 	SPINLOCK_DECLARE(lock);
 	link_t list;
 	answerbox_t *callee;
 	int busy;
-} phone_t;
+	atomic_t active_calls;
+};
+
+typedef struct {
+	link_t list;
+
+	int flags;
+
+	/* Identification of the caller */
+	task_t *sender;
+	/* The caller box is different from sender->answerbox
+	 * for synchronous calls
+	 */
+	answerbox_t *callerbox;
+
+	ipc_data_t data;
+}call_t;
 
 extern void ipc_init(void);
@@ -166,5 +184,4 @@
 extern void ipc_call(phone_t *phone, call_t *request);
 extern void ipc_call_sync(phone_t *phone, call_t *request);
-extern void ipc_phone_destroy(phone_t *phone);
 extern void ipc_phone_init(phone_t *phone);
 extern void ipc_phone_connect(phone_t *phone, answerbox_t *box);
@@ -178,4 +195,5 @@
 extern answerbox_t *ipc_phone_0;
 extern void ipc_cleanup(task_t *task);
+extern int ipc_phone_hangup(phone_t *phone);
 
 #endif
Index: generic/include/ipc/ipcrsc.h
===================================================================
--- generic/include/ipc/ipcrsc.h	(revision ba81cab60a5926ed0eb9888e74ef22a77ec9792e)
+++ generic/include/ipc/ipcrsc.h	(revision b4b45210fc5bef84b7f8456d96320f10dd3f5245)
@@ -32,7 +32,6 @@
 call_t * get_call(__native callid);
 int phone_alloc(void);
+void phone_connect(int phoneid, answerbox_t *box);
 void phone_dealloc(int phoneid);
-void phone_connect(int phoneid, answerbox_t *box);
-
 
 #endif
Index: generic/include/ipc/sysipc.h
===================================================================
--- generic/include/ipc/sysipc.h	(revision ba81cab60a5926ed0eb9888e74ef22a77ec9792e)
+++ generic/include/ipc/sysipc.h	(revision b4b45210fc5bef84b7f8456d96320f10dd3f5245)
@@ -31,13 +31,13 @@
 
 __native sys_ipc_call_sync_fast(__native phoneid, __native method, 
-				__native arg1, __native *data);
-__native sys_ipc_call_sync(__native phoneid, __native *question, 
-			   __native *reply);
+				__native arg1, ipc_data_t *data);
+__native sys_ipc_call_sync(__native phoneid, ipc_data_t *question, 
+			   ipc_data_t *reply);
 __native sys_ipc_call_async_fast(__native phoneid, __native method, 
 				 __native arg1, __native arg2);
-__native sys_ipc_call_async(__native phoneid, __native *data);
+__native sys_ipc_call_async(__native phoneid, ipc_data_t *data);
 __native sys_ipc_answer_fast(__native callid, __native retval, 
 			     __native arg1, __native arg2);
-__native sys_ipc_answer(__native callid, __native *data);
+__native sys_ipc_answer(__native callid, ipc_data_t *data);
 __native sys_ipc_connect_to_me(__native phoneid, __native arg1,
 			       __native arg2, task_id_t *taskid);
@@ -48,4 +48,5 @@
 __native sys_ipc_forward_fast(__native callid, __native phoneid,
 			      __native method, __native arg1);
+__native sys_ipc_hangup(int phoneid);
 
 
Index: generic/include/syscall/syscall.h
===================================================================
--- generic/include/syscall/syscall.h	(revision ba81cab60a5926ed0eb9888e74ef22a77ec9792e)
+++ generic/include/syscall/syscall.h	(revision b4b45210fc5bef84b7f8456d96320f10dd3f5245)
@@ -46,4 +46,5 @@
 	SYS_IPC_CONNECT_TO_ME,
 	SYS_IPC_CONNECT_ME_TO,
+	SYS_IPC_HANGUP,
 	SYSCALL_END
 } syscall_t;
Index: generic/src/ipc/ipc.c
===================================================================
--- generic/src/ipc/ipc.c	(revision ba81cab60a5926ed0eb9888e74ef22a77ec9792e)
+++ generic/src/ipc/ipc.c	(revision b4b45210fc5bef84b7f8456d96320f10dd3f5245)
@@ -124,26 +124,4 @@
 }
 
-/** Disconnect phone from answerbox
- *
- * It is allowed to call disconnect on already disconnected phone\
- */
-void ipc_phone_destroy(phone_t *phone)
-{
-	answerbox_t *box = phone->callee;
-	
-	ASSERT(box);
-
-	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);
-}
-
 /** Helper function to facilitate synchronous calls */
 void ipc_call_sync(phone_t *phone, call_t *request)
@@ -191,4 +169,16 @@
 }
 
+/* Unsafe unchecking ipc_call */
+static void _ipc_call(phone_t *phone, answerbox_t *box, call_t *call)
+{
+	atomic_inc(&phone->active_calls);
+	call->data.phone = phone;
+
+	spinlock_lock(&box->lock);
+	list_append(&call->list, &box->calls);
+	spinlock_unlock(&box->lock);
+	waitq_wakeup(&box->wq, 0);
+}
+
 /** Send a asynchronous request using phone to answerbox
  *
@@ -201,18 +191,53 @@
 
 	spinlock_lock(&phone->lock);
+
 	box = phone->callee;
 	if (!box) {
 		/* Trying to send over disconnected phone */
+		spinlock_unlock(&phone->lock);
+
+		call->data.phone = phone;
 		IPC_SET_RETVAL(call->data, ENOENT);
 		_ipc_answer_free_call(call);
 		return;
 	}
-
-	spinlock_lock(&box->lock);
-	list_append(&call->list, &box->calls);
-	spinlock_unlock(&box->lock);
-	waitq_wakeup(&box->wq, 0);
+	_ipc_call(phone, box, call);
 	
 	spinlock_unlock(&phone->lock);
+}
+
+/** Disconnect phone from answerbox
+ *
+ * It is allowed to call disconnect on already disconnected phone
+ *
+ * @return 0 - phone disconnected, -1 - the phone was already disconnected
+ */
+int ipc_phone_hangup(phone_t *phone)
+{
+	answerbox_t *box;
+	call_t *call;
+	
+	spinlock_lock(&phone->lock);
+	box = phone->callee;
+	if (!box) {
+		spinlock_unlock(&phone->lock);
+		return -1;
+	}
+
+	spinlock_lock(&box->lock);
+	list_remove(&phone->list);
+	phone->callee = NULL;
+	spinlock_unlock(&box->lock);
+
+	call = ipc_call_alloc();
+	IPC_SET_METHOD(call->data, IPC_M_PHONE_HUNGUP);
+	call->flags |= IPC_CALL_DISCARD_ANSWER;
+	_ipc_call(phone, box, call);
+
+	phone->busy = 0;
+
+	spinlock_unlock(&phone->lock);
+
+	return 0;
 }
 
@@ -226,4 +251,5 @@
 {
 	spinlock_lock(&oldbox->lock);
+	atomic_dec(&call->data.phone->active_calls);
 	list_remove(&call->list);
 	spinlock_unlock(&oldbox->lock);
@@ -242,28 +268,30 @@
 	call_t *request;
 
-	spinlock_lock(&box->lock);
-	while (1) { 
-		if (!list_empty(&box->answers)) {
-			/* Handle asynchronous answers */
-			request = list_get_instance(box->answers.next, call_t, list);
-			list_remove(&request->list);
-		} else if (!list_empty(&box->calls)) {
-			/* Handle requests */
-			request = list_get_instance(box->calls.next, call_t, list);
-			list_remove(&request->list);
-			/* Append request to dispatch queue */
-			list_append(&request->list, &box->dispatched_calls);
-			request->flags |= IPC_CALL_DISPATCHED;
-		} else {
-			if (!(flags & IPC_WAIT_NONBLOCKING)) {
-				/* Wait for event to appear */
-				spinlock_unlock(&box->lock);
-				waitq_sleep(&box->wq);
-				spinlock_lock(&box->lock);
-				continue;
-			}
-			request = NULL;
-		}
-		break;
+restart:      
+	if (flags & IPC_WAIT_NONBLOCKING) {
+		if (waitq_sleep_timeout(&box->wq,0,1) == ESYNCH_WOULD_BLOCK)
+			return NULL;
+	} else 
+		waitq_sleep(&box->wq);
+	
+	spinlock_lock(&box->lock);
+	if (!list_empty(&box->answers)) {
+		/* Handle asynchronous answers */
+		request = list_get_instance(box->answers.next, call_t, list);
+		list_remove(&request->list);
+		printf("%d %P\n", IPC_GET_METHOD(request->data), 
+		       request->data.phone);
+		atomic_dec(&request->data.phone->active_calls);
+	} else if (!list_empty(&box->calls)) {
+		/* Handle requests */
+		request = list_get_instance(box->calls.next, call_t, list);
+		list_remove(&request->list);
+		/* Append request to dispatch queue */
+		list_append(&request->list, &box->dispatched_calls);
+		request->flags |= IPC_CALL_DISPATCHED;
+	} else {
+		printf("WARNING: Spurious IPC wakeup.\n");
+		spinlock_unlock(&box->lock);
+		goto restart;
 	}
 	spinlock_unlock(&box->lock);
Index: generic/src/ipc/ipcrsc.c
===================================================================
--- generic/src/ipc/ipcrsc.c	(revision ba81cab60a5926ed0eb9888e74ef22a77ec9792e)
+++ generic/src/ipc/ipcrsc.c	(revision b4b45210fc5bef84b7f8456d96320f10dd3f5245)
@@ -37,4 +37,6 @@
  * - find phone in slot and send a message using phone
  * - answer message to phone
+ * - hangup phone (the caller has hung up)
+ * - hangup phone (the answerbox is exiting)
  * 
  * Locking strategy
@@ -51,15 +53,6 @@
  *   and proper reply will be generated.
  *
- * - There may be objection that a race may occur when the syscall finds
- *   an appropriate call and before executing ipc_send, the phone call might
- *   be disconnected and connected elsewhere. As there is no easy solution,
- *   the application will be notified by an  'PHONE_DISCONNECTED' message
- *   and the phone will not be allocated before the application notifies
- *   the kernel subsystem that it does not have any pending calls regarding
- *   this phone call.
- *
  * Locking order
  *
- * There are 2 possibilities
  * - first phone, then answerbox
  *   + Easy locking on calls
@@ -68,26 +61,31 @@
  *     The only possibility is try_lock with restart of list traversal.
  *
- * - first answerbox, then phone(s)
- *   + Easy phone disconnect
- *   - Multiple checks needed when sending message
+ * Destroying is less frequent, this approach is taken.
  *
- * Because the answerbox destroyal is much less frequent operation, 
- * the first method is chosen.
+ * Phone hangup
+ * 
+ * *** The caller hangs up (sys_ipc_hangup) ***
+ * - The phone is disconnected (no more messages can be sent over this phone),
+ *   all in-progress messages are correctly handled. The anwerbox receives
+ *   IPC_M_PHONE_HUNGUP call from the phone that hung up. When all async
+ *   calls are answered, the phone is deallocated.
+ *
+ * *** The answerbox hangs up (ipc_answer(ESLAM))
+ * - The phone is disconnected. IPC_M_ANSWERBOX_HUNGUP notification
+ *   is sent to source task, the calling process is expected to
+ *   send an sys_ipc_hangup after cleaning up it's internal structures.
  *
  * Cleanup strategy
  * 
- * 1) Disconnect all phones.
+ * 1) Disconnect all our phones ('sys_ipc_hangup')
+ *
+ * 2) Disconnect all phones connected to answerbox.
  *    * Send message 'PHONE_DISCONNECTED' to the target application 
  * - Once all phones are disconnected, no further calls can arrive
  *
- * 2) Answer all messages in 'calls' and 'dispatched_calls' queues with
+ * 3) Answer all messages in 'calls' and 'dispatched_calls' queues with
  *    appropriate error code.
  *
- * 3) Wait for all async answers to arrive
- * Alternatively - we might try to invalidate all messages by setting some
- * flag, that would dispose of the message once it is answered. This
- * would need to link all calls in one big list, which we don't currently
- * do.
- * 
+ * 4) Wait for all async answers to arrive
  * 
  */
@@ -119,5 +117,5 @@
 	
 	for (i=0; i < IPC_MAX_PHONES; i++) {
-		if (!TASK->phones[i].busy) {
+		if (!TASK->phones[i].busy && !atomic_get(&TASK->phones[i].active_calls)) {
 			TASK->phones[i].busy = 1;
 			break;
@@ -131,5 +129,8 @@
 }
 
-/** Disconnect phone */
+/** Disconnect phone a free the slot
+ *
+ * All already sent messages will be correctly processed
+ */
 void phone_dealloc(int phoneid)
 {
@@ -137,7 +138,5 @@
 
 	ASSERT(TASK->phones[phoneid].busy);
-
-	if (TASK->phones[phoneid].callee)
-		ipc_phone_destroy(&TASK->phones[phoneid]);
+	ASSERT(! TASK->phones[phoneid].callee);
 
 	TASK->phones[phoneid].busy = 0;
Index: generic/src/ipc/sysipc.c
===================================================================
--- generic/src/ipc/sysipc.c	(revision ba81cab60a5926ed0eb9888e74ef22a77ec9792e)
+++ generic/src/ipc/sysipc.c	(revision b4b45210fc5bef84b7f8456d96320f10dd3f5245)
@@ -43,9 +43,4 @@
 #include <proc/thread.h>
 
-/* TODO: multi-threaded connect-to-me can cause race condition
- * on phone, add counter + thread_kill??
- *
- */
-
 #define GET_CHECK_PHONE(phone,phoneid,err) { \
       if (phoneid > IPC_MAX_PHONES) { err; } \
@@ -53,4 +48,5 @@
 }
 
+#define STRUCT_TO_USPACE(dst,src) copy_to_uspace(dst,src,sizeof(*src))
 
 /** Return true if the method is a system method */
@@ -69,4 +65,6 @@
 static inline int is_forwardable(__native method)
 {
+	if (method == IPC_M_PHONE_HUNGUP)
+		return 0; /* This message is meant only for the receiver */
 	return 1;
 }
@@ -82,7 +80,7 @@
 static inline int answer_will_preprocess(call_t *call)
 {
-	if (IPC_GET_METHOD(call->data) == IPC_M_CONNECTTOME)
+	if (IPC_GET_METHOD(call->data) == IPC_M_CONNECT_TO_ME)
 		return 1;
-	if (IPC_GET_METHOD(call->data) == IPC_M_CONNECTMETO)
+	if (IPC_GET_METHOD(call->data) == IPC_M_CONNECT_ME_TO)
 		return 1;
 	return 0;
@@ -94,5 +92,5 @@
 	int phoneid;
 
-	if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECTTOME) {
+	if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_TO_ME) {
 		phoneid = IPC_GET_ARG3(*olddata);
 		if (IPC_GET_RETVAL(answer->data)) {
@@ -103,5 +101,5 @@
 			phone_connect(phoneid,&answer->sender->answerbox);
 		}
-	} else if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECTMETO) {
+	} else if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_ME_TO) {
 		/* If the users accepted call, connect */
 		if (!IPC_GET_RETVAL(answer->data)) {
@@ -131,5 +129,5 @@
 	int phoneid;
 
-	if (IPC_GET_METHOD(call->data) == IPC_M_CONNECTTOME) {
+	if (IPC_GET_METHOD(call->data) == IPC_M_CONNECT_TO_ME) {
 		phoneid = phone_alloc();
 		if (phoneid < 0) { /* Failed to allocate phone */
@@ -149,5 +147,5 @@
  */
 __native sys_ipc_call_sync_fast(__native phoneid, __native method, 
-				__native arg1, __native *data)
+				__native arg1, ipc_data_t *data)
 {
 	call_t call;
@@ -165,5 +163,5 @@
 	ipc_call_sync(phone, &call);
 
-	copy_to_uspace(data, &call.data, sizeof(call.data));
+	STRUCT_TO_USPACE(&data->args, &call.data.args);
 
 	return 0;
@@ -171,6 +169,6 @@
 
 /** Synchronous IPC call allowing to send whole message */
-__native sys_ipc_call_sync(__native phoneid, __native *question, 
-			   __native *reply)
+__native sys_ipc_call_sync(__native phoneid, ipc_data_t *question, 
+			   ipc_data_t *reply)
 {
 	call_t call;
@@ -178,5 +176,5 @@
 
 	ipc_call_static_init(&call);
-	copy_from_uspace(&call.data, question, sizeof(call.data));
+	copy_from_uspace(&call.data.args, &question->args, sizeof(call.data.args));
 
 	if (is_system_method(IPC_GET_METHOD(call.data)))
@@ -187,5 +185,5 @@
 	ipc_call_sync(phone, &call);
 
-	copy_to_uspace(reply, &call.data, sizeof(call.data));
+	STRUCT_TO_USPACE(&reply->args, &call.data.args);
 
 	return 0;
@@ -238,5 +236,5 @@
  * @return The same as sys_ipc_call_async
  */
-__native sys_ipc_call_async(__native phoneid, __native *data)
+__native sys_ipc_call_async(__native phoneid, ipc_data_t *data)
 {
 	call_t *call;
@@ -249,5 +247,5 @@
 
 	call = ipc_call_alloc();
-	copy_from_uspace(&call->data, data, sizeof(call->data));
+	copy_from_uspace(&call->data.args, &data->args, sizeof(call->data.args));
 
 	if (is_system_method(IPC_GET_METHOD(call->data))) {
@@ -335,5 +333,5 @@
 
 /** Send IPC answer */
-inline __native sys_ipc_answer(__native callid, __native *data)
+__native sys_ipc_answer(__native callid, ipc_data_t *data)
 {
 	call_t *call;
@@ -349,5 +347,6 @@
 		preprocess = 1;
 	}
-	copy_from_uspace(&call->data, data, sizeof(call->data));
+	copy_from_uspace(&call->data.args, &data->args, 
+			 sizeof(call->data.args));
 
 	if (preprocess)
@@ -370,5 +369,5 @@
 
 	ipc_call_static_init(&call);
-	IPC_SET_METHOD(call.data, IPC_M_CONNECTTOME);
+	IPC_SET_METHOD(call.data, IPC_M_CONNECT_TO_ME);
 	IPC_SET_ARG1(call.data, arg1);
 	IPC_SET_ARG2(call.data, arg2);
@@ -379,7 +378,5 @@
 
 	if (!IPC_GET_RETVAL(call.data) && taskid)
-		copy_to_uspace(taskid, 
-			       &phone->callee->task->taskid,
-			       sizeof(TASK->taskid));
+		STRUCT_TO_USPACE(taskid, &phone->callee->task->taskid);
 
 	return IPC_GET_RETVAL(call.data);
@@ -404,5 +401,5 @@
 
 	ipc_call_static_init(&call);
-	IPC_SET_METHOD(call.data, IPC_M_CONNECTMETO);
+	IPC_SET_METHOD(call.data, IPC_M_CONNECT_ME_TO);
 	IPC_SET_ARG1(call.data, arg1);
 	IPC_SET_ARG2(call.data, arg2);
@@ -419,17 +416,31 @@
 }
 
+/** Hang up the phone
+ *
+ * 
+ *
+ */
+__native sys_ipc_hangup(int phoneid)
+{
+	phone_t *phone;
+
+	GET_CHECK_PHONE(phone, phoneid, return ENOENT);
+
+	if (ipc_phone_hangup(phone))
+		return -1;
+
+	return 0;
+}
+
 /** Wait for incoming ipc call or answer
  *
- * Generic function - can serve either as inkernel or userspace call
- * - inside kernel does probably unnecessary copying of data (TODO)
- *
- * @param result 
- * @param taskid 
+ * @param calldata Pointer to buffer where the call/answer data is stored 
+ * @param taskid On 'CONNECT_ME_TO' call it is filled with 'taskid' of
+ *               the caller.
  * @param flags
  * @return Callid, if callid & 1, then the call is answer
  */
-inline __native sys_ipc_wait_for_call(ipc_data_t *calldata, 
-				      task_id_t *taskid,
-				      __native flags)
+__native sys_ipc_wait_for_call(ipc_data_t *calldata, task_id_t *taskid,
+			       __native flags)
 					     
 {
@@ -443,16 +454,26 @@
 			goto restart;
 
-		copy_to_uspace(calldata, &call->data, sizeof(call->data));
+		ASSERT(! (call->flags & IPC_CALL_STATIC_ALLOC));
+
 		atomic_dec(&TASK->active_calls);
-		ASSERT(! (call->flags & IPC_CALL_STATIC_ALLOC));
+
+		if (call->flags & IPC_CALL_DISCARD_ANSWER) {
+			ipc_call_free(call);
+			goto restart;
+		}
+
+		STRUCT_TO_USPACE(&calldata->args, &call->data.args);
 		ipc_call_free(call);
 
 		return ((__native)call) | IPC_CALLID_ANSWERED;
 	}
+
 	if (process_request(&TASK->answerbox, call))
 		goto restart;
-	copy_to_uspace(calldata, &call->data, sizeof(call->data));
-	copy_to_uspace(taskid, (void *)&TASK->taskid, sizeof(TASK->taskid));
+
+	/* Include phone address('id') of the caller in the request */
+	STRUCT_TO_USPACE(calldata, &call->data);
+	if (IPC_GET_METHOD(call->data) == IPC_M_CONNECT_ME_TO)
+		STRUCT_TO_USPACE(taskid, &TASK->taskid);
 	return (__native)call;
 }
-
Index: generic/src/proc/scheduler.c
===================================================================
--- generic/src/proc/scheduler.c	(revision ba81cab60a5926ed0eb9888e74ef22a77ec9792e)
+++ generic/src/proc/scheduler.c	(revision b4b45210fc5bef84b7f8456d96320f10dd3f5245)
@@ -353,5 +353,4 @@
 		switch (THREAD->state) {
 		    case Running:
-			THREAD->state = Ready;
 			spinlock_unlock(&THREAD->lock);
 			thread_ready(THREAD);
Index: generic/src/proc/task.c
===================================================================
--- generic/src/proc/task.c	(revision ba81cab60a5926ed0eb9888e74ef22a77ec9792e)
+++ generic/src/proc/task.c	(revision b4b45210fc5bef84b7f8456d96320f10dd3f5245)
@@ -160,5 +160,5 @@
 		t = list_get_instance(cur, task_t, tasks_link);
 		spinlock_lock(&t->lock);
-		printf("%s: address=%P, taskid=%Q, as=%P, ActiveCalls: %d",
+		printf("%s: address=%P, taskid=%Q\n\tas=%P, ActiveCalls: %d",
 			t->name, t, t->taskid, t->as, atomic_get(&t->active_calls));
 		for (i=0; i < IPC_MAX_PHONES; i++) {
Index: generic/src/proc/thread.c
===================================================================
--- generic/src/proc/thread.c	(revision ba81cab60a5926ed0eb9888e74ef22a77ec9792e)
+++ generic/src/proc/thread.c	(revision b4b45210fc5bef84b7f8456d96320f10dd3f5245)
@@ -184,4 +184,6 @@
 	spinlock_lock(&t->lock);
 
+	ASSERT(! (t->state == Ready));
+
 	i = (t->priority < RQ_COUNT -1) ? ++t->priority : t->priority;
 	
@@ -416,5 +418,5 @@
 	for (cur=threads_head.next; cur!=&threads_head; cur=cur->next) {
 		t = list_get_instance(cur, thread_t, threads_link);
-		printf("%s: address=%P, tid=%d, state=%s, task=%P, code=%P, stack=%P, cpu=",
+		printf("%s: address=%P, tid=%d, state=%s\n\ttask=%P, code=%P, stack=%P, cpu=",
 			t->name, t, t->tid, thread_states[t->state], t->task, t->thread_code, t->kstack);
 		if (t->cpu)
Index: generic/src/syscall/syscall.c
===================================================================
--- generic/src/syscall/syscall.c	(revision ba81cab60a5926ed0eb9888e74ef22a77ec9792e)
+++ generic/src/syscall/syscall.c	(revision b4b45210fc5bef84b7f8456d96320f10dd3f5245)
@@ -78,4 +78,5 @@
 	sys_ipc_wait_for_call,
 	sys_ipc_connect_to_me,
-	sys_ipc_connect_me_to
+	sys_ipc_connect_me_to,
+	sys_ipc_hangup
 };
