Index: Makefile
===================================================================
--- Makefile	(revision 27810c58807c31c5a0bd750c37faf88d2199cd23)
+++ Makefile	(revision e74cb73cbab961321532b012b1090380dd325f74)
@@ -135,5 +135,6 @@
 	generic/src/synch/waitq.c \
 	generic/src/smp/ipi.c \
-	generic/src/ipc/ipc.c
+	generic/src/ipc/ipc.c \
+	generic/src/ipc/ns.c
 
 ## Test sources
Index: generic/include/ipc/ipc.h
===================================================================
--- generic/include/ipc/ipc.h	(revision 27810c58807c31c5a0bd750c37faf88d2199cd23)
+++ generic/include/ipc/ipc.h	(revision e74cb73cbab961321532b012b1090380dd325f74)
@@ -30,15 +30,44 @@
 #define __IPC_H__
 
-#define IPC_CALL_LEN    2
+/* Length of data being transfered with IPC call */
+/* - the uspace may not be able to utilize full length */
+#define IPC_CALL_LEN    4
 
 /* Flags for calls */
-#define IPC_CALL_ANSWERED    1
+#define IPC_CALL_ANSWERED      1 /**< This is answer to a call */
+#define IPC_CALL_STATIC_ALLOC  2 /**< This call will not be freed on error */
+
 /* Flags for ipc_wait_for_call */
-#define IPC_WAIT_NONBLOCKING 1
+#define IPC_WAIT_NONBLOCKING   1
+
+/* Flags of callid */
+#define IPC_CALLID_ANSWERED  1
+
+/* Return values from IPC_ASYNC */
+#define IPC_CALLRET_FATAL         -1
+#define IPC_CALLRET_TEMPORARY     -2
+
+
+/* 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])
+
+/* Well known phone descriptors */
+#define PHONE_NS              0
 
 #ifdef KERNEL
 
-#include <synch/waitq.h>
-#include <synch/spinlock.h>
+#include <synch/mutex.h>
+#include <synch/condvar.h>
 #include <adt/list.h>
 
@@ -58,5 +87,6 @@
 	SPINLOCK_DECLARE(lock);
 
-	waitq_t wq;
+	mutex_t mutex;
+	condvar_t cv;
 
 	link_t connected_phones; /**< Phones connected to this answerbox */
@@ -73,5 +103,4 @@
 } phone_t;
 
-extern void ipc_create_phonecompany(void);
 extern void ipc_init(void);
 extern call_t * ipc_wait_for_call(answerbox_t *box, int flags);
@@ -83,8 +112,9 @@
 extern void ipc_call_free(call_t *call);
 extern call_t * ipc_call_alloc(void);
-void ipc_answerbox_init(answerbox_t *box);
-void ipc_phone_init(phone_t *phone, answerbox_t *box);
+extern void ipc_answerbox_init(answerbox_t *box);
+extern void ipc_phone_init(phone_t *phone, answerbox_t *box);
+extern void ipc_call_init(call_t *call);
 
-extern answerbox_t *ipc_central_box;
+extern answerbox_t *ipc_phone_0;
 
 #endif
Index: generic/include/ipc/ns.h
===================================================================
--- generic/include/ipc/ns.h	(revision e74cb73cbab961321532b012b1090380dd325f74)
+++ generic/include/ipc/ns.h	(revision e74cb73cbab961321532b012b1090380dd325f74)
@@ -0,0 +1,46 @@
+/*
+ * 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/mm/page.h
===================================================================
--- generic/include/mm/page.h	(revision 27810c58807c31c5a0bd750c37faf88d2199cd23)
+++ generic/include/mm/page.h	(revision e74cb73cbab961321532b012b1090380dd325f74)
@@ -68,5 +68,5 @@
 } 
 
-static inline void copy_to_kernel(void *dst, void *src, count_t cnt)
+static inline void copy_from_uspace(void *dst, void *src, count_t cnt)
 {
 	memcpy(dst, src, cnt);
Index: generic/include/syscall/syscall.h
===================================================================
--- generic/include/syscall/syscall.h	(revision 27810c58807c31c5a0bd750c37faf88d2199cd23)
+++ generic/include/syscall/syscall.h	(revision e74cb73cbab961321532b012b1090380dd325f74)
@@ -34,4 +34,5 @@
 	SYS_IO,
 	SYS_IPC_CALL_SYNC,
+	SYS_IPC_CALL_SYNC_MEDIUM,
 	SYS_IPC_CALL_ASYNC,
 	SYS_IPC_ANSWER,
Index: generic/src/ipc/ipc.c
===================================================================
--- generic/src/ipc/ipc.c	(revision 27810c58807c31c5a0bd750c37faf88d2199cd23)
+++ generic/src/ipc/ipc.c	(revision e74cb73cbab961321532b012b1090380dd325f74)
@@ -32,5 +32,6 @@
  */
 
-#include <synch/waitq.h>
+#include <synch/condvar.h>
+#include <synch/mutex.h>
 #include <ipc/ipc.h>
 #include <errno.h>
@@ -44,5 +45,6 @@
 #include <proc/thread.h>
 
-answerbox_t *ipc_central_box;
+/* Open channel that is assigned automatically to new tasks */
+answerbox_t *ipc_phone_0 = NULL;
 
 static slab_cache_t *ipc_call_slab;
@@ -64,4 +66,11 @@
 }
 
+/** Initialize allocated call */
+void ipc_call_init(call_t *call)
+{
+	call->callerbox = &TASK->answerbox;
+	call->flags = IPC_CALL_STATIC_ALLOC;
+}
+
 /** Deallocate call stracuture */
 void ipc_call_free(call_t *call)
@@ -74,6 +83,6 @@
 void ipc_answerbox_init(answerbox_t *box)
 {
-	spinlock_initialize(&box->lock, "abox_lock");
-	waitq_initialize(&box->wq);
+	mutex_initialize(&box->mutex);
+	condvar_initialize(&box->cv);
 	list_initialize(&box->connected_phones);
 	list_initialize(&box->calls);
@@ -89,7 +98,8 @@
 	
 	phone->callee = box;
-	spinlock_lock(&box->lock);
+
+	mutex_lock(&box->mutex);
 	list_append(&phone->list, &box->connected_phones);
-	spinlock_unlock(&box->lock);
+	mutex_unlock(&box->mutex);
 }
 
@@ -101,7 +111,7 @@
 	ASSERT(box);
 
-	spinlock_lock(&box->lock);
+	mutex_lock(&box->mutex);
 	list_remove(&phone->list);
-	spinlock_unlock(&box->lock);
+	mutex_unlock(&box->mutex);
 }
 
@@ -131,8 +141,8 @@
 	ASSERT(box);
 
-	spinlock_lock(&box->lock);
+	mutex_lock(&box->mutex);
 	list_append(&request->list, &box->calls);
-	spinlock_unlock(&box->lock);
-	waitq_wakeup(&box->wq, 0);
+	mutex_unlock(&box->mutex);
+	condvar_signal(&box->cv);
 }
 
@@ -148,13 +158,12 @@
 	request->flags |= IPC_CALL_ANSWERED;
 
-	spinlock_lock(&box->lock);
-	spinlock_lock(&callerbox->lock);
-
+	mutex_lock(&box->mutex);
 	list_remove(&request->list);
+	mutex_unlock(&box->mutex);
+
+	mutex_lock(&callerbox->mutex);
 	list_append(&request->list, &callerbox->answers);
-	waitq_wakeup(&callerbox->wq, 0);
-
-	spinlock_unlock(&callerbox->lock);
-	spinlock_unlock(&box->lock);
+	mutex_unlock(&callerbox->mutex);
+	condvar_signal(&callerbox->cv);
 }
 
@@ -168,28 +177,28 @@
 	call_t *request;
 
-	if ((flags & IPC_WAIT_NONBLOCKING)) {
-		if (waitq_sleep_timeout(&box->wq,SYNCH_NO_TIMEOUT,SYNCH_NON_BLOCKING) == ESYNCH_WOULD_BLOCK)
-			return 0;
-	} else {
-		waitq_sleep(&box->wq);
+	mutex_lock(&box->mutex);
+	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);
+		} else {
+			if (!(flags & IPC_WAIT_NONBLOCKING)) {
+				condvar_wait(&box->cv, &box->mutex);
+				continue;
+			}
+			if (condvar_trywait(&box->cv, &box->mutex) != ESYNCH_WOULD_BLOCK)
+				continue;
+			request = NULL;
+		}
+		break;
 	}
-
-
-	// TODO - might need condition variable+mutex if we want to support
-	// removing of requests from queue before dispatch
-	spinlock_lock(&box->lock);
-	/* Handle answers first */
-	if (!list_empty(&box->answers)) {
-		request = list_get_instance(box->answers.next, call_t, list);
-		list_remove(&request->list);
-	} else {
-		ASSERT (! list_empty(&box->calls));
-		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);
-	}
-	spinlock_unlock(&box->lock);
-
+	mutex_unlock(&box->mutex);
 	return request;
 }
@@ -203,31 +212,2 @@
 					  NULL, NULL, 0);
 }
-
-static void ipc_phonecompany_thread(void *data)
-{
-	call_t *call;
-
-	printf("Phone company started.\n");
-	while (1) {
-		call = ipc_wait_for_call(&TASK->answerbox, 0);
-		printf("Received phone call - %P %P\n",
-		       call->data[0], call->data[1]);
-		call->data[0] = 0xbabaaaee;;
-		call->data[1] = 0xaaaaeeee;
-		ipc_answer(&TASK->answerbox, call);
-		printf("Call answered.\n");
-	}
-}
-
-void ipc_create_phonecompany(void)
-{
-	thread_t *t;
-	
-	if ((t = thread_create(ipc_phonecompany_thread, "phonecompany", 
-			       TASK, 0)))
-		thread_ready(t);
-	else
-		panic("thread_create/phonecompany");
-
-	ipc_central_box = &TASK->answerbox;
-}
Index: generic/src/ipc/ns.c
===================================================================
--- generic/src/ipc/ns.c	(revision e74cb73cbab961321532b012b1090380dd325f74)
+++ generic/src/ipc/ns.c	(revision e74cb73cbab961321532b012b1090380dd325f74)
@@ -0,0 +1,74 @@
+/*
+ * 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.\n");
+			IPC_SET_RETVAL(call->data, 0);
+			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/main/kinit.c
===================================================================
--- generic/src/main/kinit.c	(revision 27810c58807c31c5a0bd750c37faf88d2199cd23)
+++ generic/src/main/kinit.c	(revision e74cb73cbab961321532b012b1090380dd325f74)
@@ -48,4 +48,5 @@
 #include <console/kconsole.h>
 #include <elf.h>
+#include <ipc/ns.h>
 
 #ifdef CONFIG_SMP
@@ -139,5 +140,6 @@
 	interrupts_enable();
 
-	ipc_create_phonecompany();
+	/* Initialize name service */
+	ns_start();
 
 	if (config.init_size > 0) {
Index: generic/src/proc/task.c
===================================================================
--- generic/src/proc/task.c	(revision 27810c58807c31c5a0bd750c37faf88d2199cd23)
+++ generic/src/proc/task.c	(revision e74cb73cbab961321532b012b1090380dd325f74)
@@ -37,4 +37,5 @@
 #include <adt/list.h>
 #include <ipc/ipc.h>
+#include <ipc/ns.h>
 #include <memstr.h>
 
@@ -76,6 +77,6 @@
 	ipc_answerbox_init(&ta->answerbox);
 	memsetb((__address)&ta->phones, sizeof(ta->phones[0])*IPC_MAX_PHONES, 0);
-	if (ipc_central_box)
-		ipc_phone_init(&ta->phones[0], ipc_central_box);
+	if (ipc_phone_0)
+		ipc_phone_init(&ta->phones[0], ipc_phone_0);
 	
 	ipl = interrupts_disable();
Index: generic/src/syscall/syscall.c
===================================================================
--- generic/src/syscall/syscall.c	(revision 27810c58807c31c5a0bd750c37faf88d2199cd23)
+++ generic/src/syscall/syscall.c	(revision e74cb73cbab961321532b012b1090380dd325f74)
@@ -61,28 +61,52 @@
            -2 on 'Too many async request, handle answers first
  */
-static __native sys_ipc_call_sync(__native phoneid, __native arg1, 
-				   __native arg2, __native *respdata)
+static __native sys_ipc_call_sync(__native phoneid, __native method, 
+				   __native arg1, __native *data)
 {
-	call_t *call;
+	call_t call;
 	phone_t *phone;
 	/* Special answerbox for synchronous messages */
 
 	if (phoneid >= IPC_MAX_PHONES)
-		return -ENOENT;
+		return IPC_CALLRET_FATAL;
 
 	phone = &TASK->phones[phoneid];
 	if (!phone->callee)
-		return -ENOENT;
+		return IPC_CALLRET_FATAL;
 
-	call = ipc_call_alloc();
-	call->data[0] = arg1;
-	call->data[1] = arg2;
+	ipc_call_init(&call);
+	IPC_SET_METHOD(call.data, method);
+	IPC_SET_ARG1(call.data, arg1);
 	
-	ipc_call_sync(phone, call);
+	ipc_call_sync(phone, &call);
 
-	copy_to_uspace(respdata, &call->data, sizeof(__native) * IPC_CALL_LEN);
+	copy_to_uspace(data, &call.data, sizeof(call.data));
 
 	return 0;
 }
+
+static __native sys_ipc_call_sync_medium(__native phoneid, __native *data)
+{
+	call_t call;
+	phone_t *phone;
+	/* Special answerbox for synchronous messages */
+
+	if (phoneid >= IPC_MAX_PHONES)
+		return IPC_CALLRET_FATAL;
+
+	phone = &TASK->phones[phoneid];
+	if (!phone->callee)
+		return IPC_CALLRET_FATAL;
+
+	ipc_call_init(&call);
+	copy_from_uspace(&call.data, data, sizeof(call.data));
+	
+	ipc_call_sync(phone, &call);
+
+	copy_to_uspace(data, &call.data, sizeof(call.data));
+
+	return 0;
+}
+
 
 /** Send an asynchronous call over ipc
@@ -91,6 +115,6 @@
            -2 on 'Too many async request, handle answers first
  */
-static __native sys_ipc_call_async(__native phoneid, __native arg1, 
-				   __native arg2)
+static __native sys_ipc_call_async(__native phoneid, __native method, 
+				   __native arg1, __native arg2)
 {
 	call_t *call;
@@ -98,10 +122,9 @@
 
 	if (phoneid >= IPC_MAX_PHONES)
-		return -ENOENT;
+		return IPC_CALLRET_FATAL;
 
 	phone = &TASK->phones[phoneid];
 	if (!phone->callee)
-		return -ENOENT;
-
+		return IPC_CALLRET_FATAL;
 
 	/* TODO: Check that we did not exceed system imposed maximum
@@ -110,6 +133,8 @@
 	 */
 	call = ipc_call_alloc();
-	call->data[0] = arg1;
-	call->data[1] = arg2;
+	IPC_SET_METHOD(call->data, method);
+	IPC_SET_ARG1(call->data, arg1);
+	IPC_SET_ARG2(call->data, arg2);
+
 	ipc_call(phone, call);
 
@@ -118,5 +143,6 @@
 
 /** Send IPC answer */
-static __native sys_ipc_answer(__native callid, __native arg1, __native arg2)
+static __native sys_ipc_answer(__native callid, __native retval, __native arg1,
+			       __native arg2)
 {
 	call_t *call;
@@ -127,6 +153,7 @@
 	call = (call_t *) callid;
 
-	call->data[0] = arg1;
-	call->data[1] = arg2;
+	IPC_SET_RETVAL(call->data, retval);
+	IPC_SET_ARG1(call->data, arg1);
+	IPC_SET_ARG2(call->data, arg2);
 
 	ipc_answer(&TASK->answerbox, call);
@@ -145,8 +172,11 @@
 	
 	call = ipc_wait_for_call(&TASK->answerbox, flags);
-	copy_to_uspace(calldata, &call->data, sizeof(__native) * IPC_CALL_LEN);
 
-	if (call->flags & IPC_CALL_ANSWERED)
-		return ((__native)call) | 1;
+	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);
+		return ((__native)call) | IPC_CALLID_ANSWERED;
+	}
 	return (__native)call;
 }
@@ -157,4 +187,5 @@
 	sys_io,
 	sys_ipc_call_sync,
+	sys_ipc_call_sync_medium,
 	sys_ipc_call_async,
 	sys_ipc_answer,
