Index: Makefile
===================================================================
--- Makefile	(revision c23502d0c116fcac041f6a339a7791811e9f2e9c)
+++ Makefile	(revision 2d5a54f36916260c13bbe3019397b4fb1d573073)
@@ -136,5 +136,5 @@
 	generic/src/smp/ipi.c \
 	generic/src/ipc/ipc.c \
-	generic/src/ipc/ns.c
+	generic/src/ipc/sysipc.c
 
 ## Test sources
Index: generic/include/errno.h
===================================================================
--- generic/include/errno.h	(revision c23502d0c116fcac041f6a339a7791811e9f2e9c)
+++ generic/include/errno.h	(revision 2d5a54f36916260c13bbe3019397b4fb1d573073)
@@ -34,4 +34,6 @@
 #define ENOENT     -1  /* No such entry */
 #define ENOMEM     -2  /* Not enough memory */
+#define ELIMIT     -3  /* Limit exceeded */
+#define EREFUSED   -4  /* Connection refused */
 
 #endif
Index: generic/include/ipc/ipc.h
===================================================================
--- generic/include/ipc/ipc.h	(revision c23502d0c116fcac041f6a339a7791811e9f2e9c)
+++ generic/include/ipc/ipc.h	(revision 2d5a54f36916260c13bbe3019397b4fb1d573073)
@@ -69,4 +69,35 @@
 #define PHONE_NS              0
 
+/* System-specific methods - only through special syscalls
+ * These methods have special behaviour
+ */
+#define IPC_M_IAMCONNECTING   0
+/** Protocol for CONNECT - TO - ME 
+ *
+ * Calling process asks the callee to create a callback connection,
+ * so that it can start initiating new messages.
+ *
+ * The protocol for negotiating is as follows:
+ * - sys_connecttome - sends a message IPC_M_CONNECTTOME
+ * - sys_wait_for_call - upon receipt tries to allocate new phone
+ *                       - if it fails, responds with ELIMIT
+ *                     - passes call to userspace. If userspace
+ *                       responds with error, phone is deallocated and
+ *                       error is sent back to caller. Otherwise 
+ *                       the call is accepted and the response is sent back.
+ *                     - the allocated phoneid is passed to userspace as
+ *                       ARG3 of the call.
+ *                     - the caller obtains taskid of the called thread
+ */
+#define IPC_M_CONNECTTOME     1
+#define IPC_M_CONNECTMETO     2
+
+
+/* Well-known methods */
+#define IPC_M_FIRST_USER      512
+#define IPC_M_PING            512
+/* User methods */
+#define FIRST_USER_METHOD     1024
+
 #ifdef KERNEL
 
@@ -77,6 +108,6 @@
 #define IPC_MAX_PHONES  16
 
-
 typedef struct answerbox answerbox_t;
+typedef __native ipc_data_t[IPC_CALL_LEN];
 
 typedef struct {
@@ -85,9 +116,11 @@
 	int flags;
 	task_t *sender;
-	__native data[IPC_CALL_LEN];
+	ipc_data_t data;
 } call_t;
 
 struct answerbox {
 	SPINLOCK_DECLARE(lock);
+
+	task_t *task;
 
 	mutex_t mutex;
Index: neric/include/ipc/ns.h
===================================================================
--- generic/include/ipc/ns.h	(revision c23502d0c116fcac041f6a339a7791811e9f2e9c)
+++ 	(revision )
@@ -1,46 +1,0 @@
-/*
- * Copyright (C) 2006 Ondrej Palkovsky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __NS_H_
-#define __NS_H_
-
-/* NameService methods */
-
-/** Ping name service */
-#define NS_PING   1
-
-
-#ifdef KERNEL
-
-#include <ipc/ipc.h>
-
-extern void ns_start(void);
-
-#endif
-
-#endif
Index: generic/include/ipc/sysipc.h
===================================================================
--- generic/include/ipc/sysipc.h	(revision 2d5a54f36916260c13bbe3019397b4fb1d573073)
+++ generic/include/ipc/sysipc.h	(revision 2d5a54f36916260c13bbe3019397b4fb1d573073)
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2006 Ondrej Palkovsky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __SYSIPC_H__
+#define __SYSIPC_H__
+
+__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 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_answer_fast(__native callid, __native retval, 
+			     __native arg1, __native arg2);
+__native sys_ipc_answer(__native callid, __native *data);
+__native sys_ipc_connect_to_me(__native phoneid, __native arg1,
+			       __native arg2, task_id_t *taskid);
+__native sys_ipc_wait_for_call(ipc_data_t *calldata, task_id_t *taskid,
+			       __native flags);
+
+#endif
Index: generic/include/syscall/syscall.h
===================================================================
--- generic/include/syscall/syscall.h	(revision c23502d0c116fcac041f6a339a7791811e9f2e9c)
+++ generic/include/syscall/syscall.h	(revision 2d5a54f36916260c13bbe3019397b4fb1d573073)
@@ -41,4 +41,5 @@
 	SYS_IPC_ANSWER,
 	SYS_IPC_WAIT,
+	SYS_IPC_CONNECT_TO_ME,
 	SYSCALL_END
 } syscall_t;
Index: generic/src/ipc/ipc.c
===================================================================
--- generic/src/ipc/ipc.c	(revision c23502d0c116fcac041f6a339a7791811e9f2e9c)
+++ generic/src/ipc/ipc.c	(revision 2d5a54f36916260c13bbe3019397b4fb1d573073)
@@ -72,4 +72,5 @@
 	call->callerbox = &TASK->answerbox;
 	call->flags = IPC_CALL_STATIC_ALLOC;
+	call->sender = TASK;
 }
 
@@ -90,4 +91,5 @@
 	list_initialize(&box->dispatched_calls);
 	list_initialize(&box->answers);
+	box->task = TASK;
 }
 
Index: neric/src/ipc/ns.c
===================================================================
--- generic/src/ipc/ns.c	(revision c23502d0c116fcac041f6a339a7791811e9f2e9c)
+++ 	(revision )
@@ -1,77 +1,0 @@
-/*
- * Copyright (C) 2006 Ondrej Palkovsky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <ipc/ipc.h>
-#include <ipc/ns.h>
-#include <print.h>
-#include <proc/thread.h>
-#include <arch.h>
-#include <panic.h>
-
-static answerbox_t ns_answerbox;
-
-/**   */
-static void ns_thread(void *data)
-{
-	call_t *call;
-
-	printf("Name service started.\n");
-	while (1) {
-		call = ipc_wait_for_call(&ns_answerbox, 0);
-		switch (IPC_GET_METHOD(call->data)) {
-		case NS_PING:
-			printf("Ping - %X, %X\n", IPC_GET_ARG1(call->data),
-			       IPC_GET_ARG2(call->data));
-			IPC_SET_RETVAL(call->data, 0);
-			IPC_SET_ARG1(call->data, 0xdeaddead);
-			IPC_SET_ARG2(call->data, 0xdeaddea2);
-			break;
-		default:
-			printf("Unsupported name service call.\n");
-			IPC_SET_RETVAL(call->data, -1);
-		}
-		ipc_answer(&ns_answerbox, call);
-	}
-}
-
-/** Name service initialization and start
- *
- * This must be started before any task that communicates with name service
- */
-void ns_start(void)
-{
-	thread_t *t;
-
-	ipc_answerbox_init(&ns_answerbox);
-	ipc_phone_0 = &ns_answerbox;
-	
-	if ((t = thread_create(ns_thread, NULL, TASK, 0)))
-		thread_ready(t);
-	else
-		panic("thread_create/phonecompany");
-}
Index: generic/src/ipc/sysipc.c
===================================================================
--- generic/src/ipc/sysipc.c	(revision 2d5a54f36916260c13bbe3019397b4fb1d573073)
+++ generic/src/ipc/sysipc.c	(revision 2d5a54f36916260c13bbe3019397b4fb1d573073)
@@ -0,0 +1,383 @@
+/*
+ * Copyright (C) 2006 Ondrej Palkovsky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <arch.h>
+#include <proc/task.h>
+
+#include <errno.h>
+#include <mm/page.h>
+#include <memstr.h>
+#include <debug.h>
+#include <ipc/ipc.h>
+#include <ipc/sysipc.h>
+#include <print.h>
+
+/* TODO: multi-threaded connect-to-me can cause race condition
+ * on phone, add counter + thread_kill??
+ *
+ * - don't allow userspace app to send system messages
+ */
+
+/** Return pointer to phone identified by phoneid or NULL if non-existent */
+static phone_t * get_phone(__native phoneid)
+{
+	phone_t *phone;
+
+	if (phoneid >= IPC_MAX_PHONES)
+		return NULL;
+
+	phone = &TASK->phones[phoneid];
+	if (!phone->callee)
+		return NULL;
+	return phone;
+}
+
+/** Allocate new phone slot in current TASK structure */
+static int phone_alloc(answerbox_t *callee)
+{
+	int i;
+
+	spinlock_lock(&TASK->lock);
+	
+	for (i=0; i < IPC_MAX_PHONES; i++) {
+		if (!TASK->phones[i].callee) {
+			TASK->phones[i].callee = callee;
+			break;
+		}
+	}
+	spinlock_unlock(&TASK->lock);
+
+	if (i >= IPC_MAX_PHONES)
+		return -1;
+	return i;
+}
+
+/** Disconnect phone */
+static void phone_dealloc(int phoneid)
+{
+	spinlock_lock(TASK->lock);
+
+	ASSERT(TASK->phones[phoneid].callee);
+
+	TASK->phones[phoneid].callee = NULL;
+	spinlock_unlock(TASK->lock);
+}
+
+/****************************************************/
+/* Functions that preprocess answer before sending 
+ * it to the recepient
+ */
+
+/** Return true if the caller (ipc_answer) should save
+ * the old call contents and call answer_preprocess
+ */
+static inline int answer_will_preprocess(call_t *call)
+{
+	if (IPC_GET_METHOD(call->data) == IPC_M_CONNECTTOME)
+		return 1;
+	return 0;
+}
+
+/** Interpret process answer as control information */
+static inline void answer_preprocess(call_t *answer, call_t *call)
+{
+	int phoneid;
+
+	if (IPC_GET_METHOD(call->data) == IPC_M_CONNECTTOME) {
+		if (IPC_GET_RETVAL(answer->data)) {
+			/* The connection was not accepted */
+			/* TODO...race for multi-threaded process */
+			phoneid = IPC_GET_ARG3(call->data);
+			phone_dealloc(phoneid);
+		}
+	}
+}
+
+/****************************************************/
+/* Functions called to process received call/answer 
+ * before passing to uspace
+ */
+
+/** Do basic kernel processing of received call answer */
+static int process_answer(answerbox_t *box,call_t *call)
+{
+	return 0;
+}
+
+/** Do basic kernel processing of received call request
+ *
+ * @return 0 - the call should be passed to userspace, 1 - ignore call
+ */
+static int process_request(answerbox_t *box,call_t *call)
+{
+	int phoneid;
+
+	if (IPC_GET_METHOD(call->data) == IPC_M_CONNECTTOME) {
+		phoneid = phone_alloc(&call->sender->answerbox);
+		if (phoneid < 0) { /* Failed to allocate phone */
+			IPC_SET_RETVAL(call->data, ELIMIT);
+			ipc_answer(box,call);
+			return -1;
+		}
+		IPC_SET_ARG3(call->data, phoneid);
+	} 
+	return 0;
+}
+
+/** Send a call over IPC, wait for reply, return to user
+ *
+ * @return Call identification, returns -1 on fatal error, 
+           -2 on 'Too many async request, handle answers first
+ */
+__native sys_ipc_call_sync_fast(__native phoneid, __native method, 
+				__native arg1, __native *data)
+{
+	call_t call;
+	phone_t *phone;
+
+	phone = get_phone(phoneid);
+	if (!phone)
+		return IPC_CALLRET_FATAL;
+
+	ipc_call_init(&call);
+	IPC_SET_METHOD(call.data, method);
+	IPC_SET_ARG1(call.data, arg1);
+	
+	ipc_call_sync(phone, &call);
+
+	copy_to_uspace(data, &call.data, sizeof(call.data));
+
+	return 0;
+}
+
+/** Synchronous IPC call allowing to send whole message */
+__native sys_ipc_call_sync(__native phoneid, __native *question, 
+			   __native *reply)
+{
+	call_t call;
+	phone_t *phone;
+
+	phone = get_phone(phoneid);
+	if (!phone)
+		return IPC_CALLRET_FATAL;
+
+	ipc_call_init(&call);
+	copy_from_uspace(&call.data, question, sizeof(call.data));
+	
+	ipc_call_sync(phone, &call);
+
+	copy_to_uspace(reply, &call.data, sizeof(call.data));
+
+	return 0;
+}
+
+/** Check that the task did not exceed allowed limit
+ *
+ * @return 0 - Limit OK,   -1 - limit exceeded
+ */
+static int check_call_limit(void)
+{
+	if (atomic_preinc(&TASK->active_calls) > IPC_MAX_ASYNC_CALLS) {
+		atomic_dec(&TASK->active_calls);
+		return -1;
+	}
+	return 0;
+}
+
+/** Send an asynchronous call over ipc
+ *
+ * @return Call identification, returns -1 on fatal error, 
+           -2 on 'Too many async request, handle answers first
+ */
+__native sys_ipc_call_async_fast(__native phoneid, __native method, 
+				 __native arg1, __native arg2)
+{
+	call_t *call;
+	phone_t *phone;
+
+	phone = get_phone(phoneid);
+	if (!phone)
+		return IPC_CALLRET_FATAL;
+
+	if (check_call_limit())
+		return IPC_CALLRET_TEMPORARY;
+
+	call = ipc_call_alloc();
+	IPC_SET_METHOD(call->data, method);
+	IPC_SET_ARG1(call->data, arg1);
+	IPC_SET_ARG2(call->data, arg2);
+
+	ipc_call(phone, call);
+
+	return (__native) call;
+}
+
+/** Synchronous IPC call allowing to send whole message
+ *
+ * @return The same as sys_ipc_call_async
+ */
+__native sys_ipc_call_async(__native phoneid, __native *data)
+{
+	call_t *call;
+	phone_t *phone;
+
+	phone = get_phone(phoneid);
+	if (!phone)
+		return IPC_CALLRET_FATAL;
+
+	if (check_call_limit())
+		return IPC_CALLRET_TEMPORARY;
+
+	call = ipc_call_alloc();
+	copy_from_uspace(&call->data, data, sizeof(call->data));
+	
+	ipc_call(phone, call);
+
+	return (__native) call;
+}
+
+/** Send IPC answer */
+__native sys_ipc_answer_fast(__native callid, __native retval, 
+			     __native arg1, __native arg2)
+{
+	call_t *call;
+	call_t saved_call;
+	int preprocess = 0;
+
+	/* Check that the user is not sending us answer callid */
+	ASSERT(! (callid & 1));
+	/* TODO: Check that the callid is in the dispatch table */
+	call = (call_t *) callid;
+
+	if (answer_will_preprocess(call)) {
+		memcpy(&saved_call.data, &call->data, sizeof(call->data));
+		preprocess = 1;
+	}
+
+	IPC_SET_RETVAL(call->data, retval);
+	IPC_SET_ARG1(call->data, arg1);
+	IPC_SET_ARG2(call->data, arg2);
+	if (preprocess)
+		answer_preprocess(call, &saved_call);
+
+	ipc_answer(&TASK->answerbox, call);
+	return 0;
+}
+
+/** Send IPC answer */
+inline __native sys_ipc_answer(__native callid, __native *data)
+{
+	call_t *call;
+	call_t saved_call;
+	int preprocess = 0;
+
+	/* Check that the user is not sending us answer callid */
+	ASSERT(! (callid & 1));
+	/* TODO: Check that the callid is in the dispatch table */
+	call = (call_t *) callid;
+
+	if (answer_will_preprocess(call)) {
+		memcpy(&saved_call.data, &call->data, sizeof(call->data));
+		preprocess = 1;
+	}
+	copy_from_uspace(&call->data, data, sizeof(call->data));
+
+	if (preprocess)
+		answer_preprocess(call, &saved_call);
+	
+	ipc_answer(&TASK->answerbox, call);
+
+	return 0;
+}
+
+/** Ask the other side of connection to do 'callback' connection
+ *
+ * @return 0 if no error, error otherwise 
+ */
+__native sys_ipc_connect_to_me(__native phoneid, __native arg1,
+			       __native arg2, task_id_t *taskid)
+{
+	call_t call;
+	phone_t *phone;
+
+	phone = get_phone(phoneid);
+	if (!phone)
+		return IPC_CALLRET_FATAL;
+
+	ipc_call_init(&call);
+	IPC_SET_METHOD(call.data, IPC_M_CONNECTTOME);
+	IPC_SET_ARG1(call.data, arg1);
+	IPC_SET_ARG2(call.data, arg2);
+	
+	ipc_call_sync(phone, &call);
+
+	if (!IPC_GET_RETVAL(call.data) && taskid)
+		copy_to_uspace(taskid, 
+			       &phone->callee->task->taskid,
+			       sizeof(TASK->taskid));
+	return IPC_GET_RETVAL(call.data);
+}
+
+/** 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 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)
+					     
+{
+	call_t *call;
+
+restart:	
+	call = ipc_wait_for_call(&TASK->answerbox, flags);
+
+	if (call->flags & IPC_CALL_ANSWERED) {
+		if (process_answer(&TASK->answerbox, call))
+			goto restart;
+
+		copy_to_uspace(calldata, &call->data, sizeof(call->data));
+		atomic_dec(&TASK->active_calls);
+		ASSERT(! (call->flags & IPC_CALL_STATIC_ALLOC));
+		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));
+	return (__native)call;
+}
+
Index: generic/src/main/kinit.c
===================================================================
--- generic/src/main/kinit.c	(revision c23502d0c116fcac041f6a339a7791811e9f2e9c)
+++ generic/src/main/kinit.c	(revision 2d5a54f36916260c13bbe3019397b4fb1d573073)
@@ -46,5 +46,4 @@
 #include <interrupt.h>
 #include <console/kconsole.h>
-#include <ipc/ns.h>
 
 #ifdef CONFIG_SMP
@@ -70,4 +69,5 @@
 {
 	thread_t *t;
+	task_t *utask;
 
 	interrupts_disable();
@@ -134,7 +134,4 @@
 	interrupts_enable();
 
-	/* Initialize name service */
-	ns_start();
-
 	if (config.init_size > 0) {
 		/*
@@ -145,7 +142,9 @@
 			panic("config.init_addr is not frame aligned");
 
-		if (!task_run_program((void *)config.init_addr)) {
+		utask = task_run_program((void *)config.init_addr);
+		if (utask) 
+			ipc_phone_0 = &utask->answerbox;
+		else 
 			printf("Userspace not started.\n");
-		}
 	}
 
Index: generic/src/syscall/syscall.c
===================================================================
--- generic/src/syscall/syscall.c	(revision c23502d0c116fcac041f6a339a7791811e9f2e9c)
+++ generic/src/syscall/syscall.c	(revision 2d5a54f36916260c13bbe3019397b4fb1d573073)
@@ -32,9 +32,9 @@
 #include <print.h>
 #include <putchar.h>
-#include <ipc/ipc.h>
 #include <errno.h>
 #include <proc/task.h>
 #include <arch.h>
 #include <debug.h>
+#include <ipc/sysipc.h>
 
 static __native sys_ctl(void) {
@@ -57,190 +57,4 @@
 }
 
-static phone_t * get_phone(__native phoneid)
-{
-	phone_t *phone;
-
-	if (phoneid >= IPC_MAX_PHONES)
-		return NULL;
-
-	phone = &TASK->phones[phoneid];
-	if (!phone->callee)
-		return NULL;
-	return phone;
-}
-
-/** Send a call over IPC, wait for reply, return to user
- *
- * @return Call identification, returns -1 on fatal error, 
-           -2 on 'Too many async request, handle answers first
- */
-static __native sys_ipc_call_sync_fast(__native phoneid, __native method, 
-				       __native arg1, __native *data)
-{
-	call_t call;
-	phone_t *phone;
-	/* Special answerbox for synchronous messages */
-
-	phone = get_phone(phoneid);
-	if (!phone)
-		return IPC_CALLRET_FATAL;
-
-	ipc_call_init(&call);
-	IPC_SET_METHOD(call.data, method);
-	IPC_SET_ARG1(call.data, arg1);
-	
-	ipc_call_sync(phone, &call);
-
-	copy_to_uspace(data, &call.data, sizeof(call.data));
-
-	return 0;
-}
-
-/** Synchronous IPC call allowing to send whole message */
-static __native sys_ipc_call_sync(__native phoneid, __native *question, 
-				  __native *reply)
-{
-	call_t call;
-	phone_t *phone;
-	/* Special answerbox for synchronous messages */
-
-	phone = get_phone(phoneid);
-	if (!phone)
-		return IPC_CALLRET_FATAL;
-
-	ipc_call_init(&call);
-	copy_from_uspace(&call.data, question, sizeof(call.data));
-	
-	ipc_call_sync(phone, &call);
-
-	copy_to_uspace(reply, &call.data, sizeof(call.data));
-
-	return 0;
-}
-
-/** Check that the task did not exceed allowed limit
- *
- * @return 0 - Limit OK,   -1 - limit exceeded
- */
-static int check_call_limit(void)
-{
-	if (atomic_preinc(&TASK->active_calls) > IPC_MAX_ASYNC_CALLS) {
-		atomic_dec(&TASK->active_calls);
-		return -1;
-	}
-	return 0;
-}
-
-/** Send an asynchronous call over ipc
- *
- * @return Call identification, returns -1 on fatal error, 
-           -2 on 'Too many async request, handle answers first
- */
-static __native sys_ipc_call_async_fast(__native phoneid, __native method, 
-					__native arg1, __native arg2)
-{
-	call_t *call;
-	phone_t *phone;
-
-	phone = get_phone(phoneid);
-	if (!phone)
-		return IPC_CALLRET_FATAL;
-
-	if (check_call_limit())
-		return IPC_CALLRET_TEMPORARY;
-
-	call = ipc_call_alloc();
-	IPC_SET_METHOD(call->data, method);
-	IPC_SET_ARG1(call->data, arg1);
-	IPC_SET_ARG2(call->data, arg2);
-
-	ipc_call(phone, call);
-
-	return (__native) call;
-}
-
-/** Synchronous IPC call allowing to send whole message
- *
- * @return The same as sys_ipc_call_async
- */
-static __native sys_ipc_call_async(__native phoneid, __native *data)
-{
-	call_t *call;
-	phone_t *phone;
-
-	phone = get_phone(phoneid);
-	if (!phone)
-		return IPC_CALLRET_FATAL;
-
-	if (check_call_limit())
-		return IPC_CALLRET_TEMPORARY;
-
-	call = ipc_call_alloc();
-	copy_from_uspace(&call->data, data, sizeof(call->data));
-	
-	ipc_call(phone, call);
-
-	return (__native) call;
-}
-
-
-/** Send IPC answer */
-static __native sys_ipc_answer_fast(__native callid, __native retval, 
-				    __native arg1, __native arg2)
-{
-	call_t *call;
-
-	/* Check that the user is not sending us answer callid */
-	ASSERT(! (callid & 1));
-	/* TODO: Check that the callid is in the dispatch table */
-	call = (call_t *) callid;
-
-	IPC_SET_RETVAL(call->data, retval);
-	IPC_SET_ARG1(call->data, arg1);
-	IPC_SET_ARG2(call->data, arg2);
-
-	ipc_answer(&TASK->answerbox, call);
-	return 0;
-}
-
-/** Send IPC answer */
-static __native sys_ipc_answer(__native callid, __native *data)
-{
-	call_t *call;
-
-	/* Check that the user is not sending us answer callid */
-	ASSERT(! (callid & 1));
-	/* TODO: Check that the callid is in the dispatch table */
-	call = (call_t *) callid;
-	copy_from_uspace(&call->data, data, sizeof(call->data));
-	ipc_answer(&TASK->answerbox, call);
-
-	return 0;
-}
-
-/** Wait for incoming ipc call or answer
- *
- * @param result 
- * @param flags
- * @return Callid, if callid & 1, then the call is answer
- */
-static __native sys_ipc_wait_for_call(__native *calldata, task_id_t *taskid,
-				      __native flags)
-{
-	call_t *call;
-	
-	call = ipc_wait_for_call(&TASK->answerbox, flags);
-
-	copy_to_uspace(calldata, &call->data, sizeof(call->data));
-
-	if (call->flags & IPC_CALL_ANSWERED) {
-		ASSERT(! (call->flags & IPC_CALL_STATIC_ALLOC));
-		ipc_call_free(call);
-		atomic_dec(&TASK->active_calls);
-		return ((__native)call) | IPC_CALLID_ANSWERED;
-	}
-	copy_to_uspace(taskid, (void *)&TASK->taskid, sizeof(TASK->taskid));
-	return (__native)call;
-}
 
 static __native sys_mremap(void *address, size_t size, unsigned long flags)
@@ -259,4 +73,5 @@
 	sys_ipc_answer_fast,
 	sys_ipc_answer,
-	sys_ipc_wait_for_call
+	sys_ipc_wait_for_call,
+	sys_ipc_connect_to_me
 };
