Index: libipc/Makefile
===================================================================
--- libipc/Makefile	(revision 06502f7d46b40499a069d33845ad91047bde66bb)
+++ libipc/Makefile	(revision 936351c1f07abd9557396c96a0c7ff72a82989ec)
@@ -37,5 +37,5 @@
 include $(LIBC_PREFIX)/Makefile.toolchain
 
-CFLAGS += -Iinclude
+CFLAGS += -Iinclude -I../libadt/include -I../libc/include
 
 ## Sources
Index: libipc/generic/ipc.c
===================================================================
--- libipc/generic/ipc.c	(revision 06502f7d46b40499a069d33845ad91047bde66bb)
+++ libipc/generic/ipc.c	(revision 936351c1f07abd9557396c96a0c7ff72a82989ec)
@@ -29,12 +29,38 @@
 #include <ipc.h>
 #include <libc.h>
-
-int ipc_call_sync(int phoneid, sysarg_t method, sysarg_t arg1, 
-		  sysarg_t *result)
+#include <malloc.h>
+#include <errno.h>
+#include <list.h>
+#include <stdio.h>
+#include <unistd.h>
+
+/** Structure used for keeping track of sent async msgs 
+ * and queing unsent msgs
+ *
+ */
+typedef struct {
+	link_t list;
+
+	ipc_async_callback_t callback;
+	void *private;
+	union {
+		ipc_callid_t callid;
+		struct {
+			int phoneid;
+			ipc_data_t data;
+		} msg;
+	}u;
+} async_call_t;
+
+LIST_INITIALIZE(dispatched_calls);
+LIST_INITIALIZE(queued_calls);
+
+int ipc_call_sync(int phoneid, ipcarg_t method, ipcarg_t arg1, 
+		  ipcarg_t *result)
 {
 	ipc_data_t resdata;
 	int callres;
 	
-	callres = __SYSCALL4(SYS_IPC_CALL_SYNC, phoneid, method, arg1,
+	callres = __SYSCALL4(SYS_IPC_CALL_SYNC_FAST, phoneid, method, arg1,
 			     (sysarg_t)&resdata);
 	if (callres)
@@ -45,7 +71,7 @@
 }
 
-int ipc_call_sync_3(int phoneid, sysarg_t method, sysarg_t arg1,
-		    sysarg_t arg2, sysarg_t arg3,
-		    sysarg_t *result1, sysarg_t *result2, sysarg_t *result3)
+int ipc_call_sync_3(int phoneid, ipcarg_t method, ipcarg_t arg1,
+		    ipcarg_t arg2, ipcarg_t arg3,
+		    ipcarg_t *result1, ipcarg_t *result2, ipcarg_t *result3)
 {
 	ipc_data_t data;
@@ -57,5 +83,5 @@
 	IPC_SET_ARG3(data, arg3);
 
-	callres = __SYSCALL2(SYS_IPC_CALL_SYNC_MEDIUM, phoneid, (sysarg_t)&data);
+	callres = __SYSCALL2(SYS_IPC_CALL_SYNC, phoneid, (sysarg_t)&data);
 	if (callres)
 		return callres;
@@ -70,4 +96,10 @@
 }
 
+/** Syscall to send asynchronous message */
+static	ipc_callid_t _ipc_call_async(int phoneid, ipc_data_t *data)
+{
+	return __SYSCALL2(SYS_IPC_CALL_ASYNC, phoneid, (sysarg_t)data);
+}
+
 /** Send asynchronous message
  *
@@ -75,34 +107,47 @@
  * - if message cannot be temporarily sent, add to queue
  */
-void ipc_call_async_2(int phoneid, sysarg_t method, sysarg_t arg1,
-		      sysarg_t arg2,
+void ipc_call_async_2(int phoneid, ipcarg_t method, ipcarg_t arg1,
+		      ipcarg_t arg2, void *private,
 		      ipc_async_callback_t callback)
 {
+	async_call_t *call;
 	ipc_callid_t callid;
-	ipc_data_t data; /* Data storage for saving calls */
-
-	callid = __SYSCALL4(SYS_IPC_CALL_ASYNC, phoneid, method, arg1, arg2);
+
+	call = malloc(sizeof(*call));
+	if (!call) {
+		callback(private, ENOMEM, NULL);
+	}
+		
+	callid = __SYSCALL4(SYS_IPC_CALL_ASYNC_FAST, phoneid, method, arg1, arg2);
 	if (callid == IPC_CALLRET_FATAL) {
 		/* Call asynchronous handler with error code */
-		IPC_SET_RETVAL(data, IPC_CALLRET_FATAL);
-		callback(&data);
+		IPC_SET_RETVAL(call->u.msg.data, ENOENT);
+		callback(private, ENOENT, NULL);
+		free(call);
 		return;
 	}
+
+	call->callback = callback;
+	call->private = private;
+
 	if (callid == IPC_CALLRET_TEMPORARY) {
 		/* Add asynchronous call to queue of non-dispatched async calls */
-		IPC_SET_METHOD(data, method);
-		IPC_SET_ARG1(data, arg1);
-		IPC_SET_ARG2(data, arg2);
-		
+		call->u.msg.phoneid = phoneid;
+		IPC_SET_METHOD(call->u.msg.data, method);
+		IPC_SET_ARG1(call->u.msg.data, arg1);
+		IPC_SET_ARG2(call->u.msg.data, arg2);
+
+		list_append(&call->list, &queued_calls);
 		return;
 	}
-	/* Add callid to list of dispatched calls */
-	
+	call->u.callid = callid;
+	/* Add call to list of dispatched calls */
+	list_append(&call->list, &dispatched_calls);
 }
 
 
 /** Send answer to a received call */
-void ipc_answer(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1,
-		sysarg_t arg2)
+void ipc_answer(ipc_callid_t callid, ipcarg_t retval, ipcarg_t arg1,
+		ipcarg_t arg2)
 {
 	__SYSCALL4(SYS_IPC_ANSWER, callid, retval, arg1, arg2);
@@ -116,7 +161,63 @@
 }
 
+/** Try to dispatch queed calls from async queue */
+static void try_dispatch_queued_calls(void)
+{
+	async_call_t *call;
+	ipc_callid_t callid;
+
+	while (!list_empty(&queued_calls)) {
+		call = list_get_instance(queued_calls.next, async_call_t,
+					 list);
+
+		callid = _ipc_call_async(call->u.msg.phoneid,
+					 &call->u.msg.data);
+		if (callid == IPC_CALLRET_TEMPORARY)
+			break;
+		list_remove(&call->list);
+		if (callid == IPC_CALLRET_FATAL) {
+			call->callback(call->private, ENOENT, NULL);
+			free(call);
+		} else {
+			call->u.callid = callid;
+			list_append(&call->list, &dispatched_calls);
+		}
+	}
+}
+
+/** Handle received answer
+ *
+ * TODO: Make it use hash table
+ *
+ * @param callid Callid (with first bit set) of the answered call
+ */
+static void handle_answer(ipc_callid_t callid, ipc_data_t *data)
+{
+	link_t *item;
+	async_call_t *call;
+
+	callid &= ~IPC_CALLID_ANSWERED;
+	
+	for (item = dispatched_calls.next; item != &dispatched_calls;
+	     item = item->next) {
+		call = list_get_instance(item, async_call_t, list);
+		if (call->u.callid == callid) {
+			list_remove(&call->list);
+			call->callback(call->private, 
+				       IPC_GET_RETVAL(*data),
+				       data);
+			return;
+		}
+	}
+	printf("Received unidentified answer: %P!!!\n", callid);
+}
+
+
 /** Wait for IPC call and return
  *
  * - dispatch ASYNC reoutines in the background
+ * @param data Space where the message is stored
+ * @return Callid or 0 if nothing available and started with 
+ *         IPC_WAIT_NONBLOCKING
  */
 int ipc_wait_for_call(ipc_data_t *data, int flags)
@@ -125,10 +226,12 @@
 
 	do {
-		/* Try to dispatch non-dispatched async calls */
+		try_dispatch_queued_calls();
+
 		callid = _ipc_wait_for_call(data, flags);
-		if (callid & IPC_CALLID_ANSWERED) {
-			/* TODO: Call async answer handler */
-		}
+		/* Handle received answers */
+		if (callid & IPC_CALLID_ANSWERED)
+			handle_answer(callid, data);
 	} while (callid & IPC_CALLID_ANSWERED);
+
 	return callid;
 }
Index: libipc/include/ipc.h
===================================================================
--- libipc/include/ipc.h	(revision 06502f7d46b40499a069d33845ad91047bde66bb)
+++ libipc/include/ipc.h	(revision 936351c1f07abd9557396c96a0c7ff72a82989ec)
@@ -33,25 +33,28 @@
 #include <libc.h>
 
-typedef sysarg_t ipc_data_t[IPC_CALL_LEN];
+typedef sysarg_t ipcarg_t;
+typedef ipcarg_t ipc_data_t[IPC_CALL_LEN];
 typedef sysarg_t ipc_callid_t;
 
-typedef void (* ipc_async_callback_t)(ipc_data_t *data);
+typedef void (* ipc_async_callback_t)(void *private, 
+				      int retval,
+				      ipc_data_t *data);
 
 #define ipc_call_sync_2(phoneid, method, arg1, arg2, res1, res2) ipc_call_sync_3((phoneid), (method), (arg1), (arg2), 0, (res1), (res2), 0)
-extern int ipc_call_sync_3(int phoneid, sysarg_t method, sysarg_t arg1,
-			   sysarg_t arg2, sysarg_t arg3,
-			   sysarg_t *result1, sysarg_t *result2, 
-			   sysarg_t *result3);
+extern int ipc_call_sync_3(int phoneid, ipcarg_t method, ipcarg_t arg1,
+			   ipcarg_t arg2, ipcarg_t arg3,
+			   ipcarg_t *result1, ipcarg_t *result2, 
+			   ipcarg_t *result3);
 
 
-extern int ipc_call_sync(int phoneid, sysarg_t method, sysarg_t arg1, 
-			 sysarg_t *result);
+extern int ipc_call_sync(int phoneid, ipcarg_t method, ipcarg_t arg1, 
+			 ipcarg_t *result);
 extern int ipc_wait_for_call(ipc_data_t *data, int flags);
-extern void ipc_answer(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1,
-		       sysarg_t arg2);
+extern void ipc_answer(ipc_callid_t callid, ipcarg_t retval, ipcarg_t arg1,
+		       ipcarg_t arg2);
 
-#define ipc_call_async(phoneid,method,arg1,callback) (ipc_call_async_2(phoneid, method, arg1, 0, callback))
-void ipc_call_async_2(int phoneid, sysarg_t method, sysarg_t arg1,
-		      sysarg_t arg2,
+#define ipc_call_async(phoneid,method,arg1,private, callback) (ipc_call_async_2(phoneid, method, arg1, 0, private, callback))
+void ipc_call_async_2(int phoneid, ipcarg_t method, ipcarg_t arg1,
+		      ipcarg_t arg2, void *private,
 		      ipc_async_callback_t callback);
 
