Index: generic/src/ipc/sysipc.c
===================================================================
--- generic/src/ipc/sysipc.c	(revision ba81cab60a5926ed0eb9888e74ef22a77ec9792e)
+++ generic/src/ipc/sysipc.c	(revision fbcfd458644bcd6959780591c4684c38aae47cc6)
@@ -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;
 }
-
