← Back to team overview

helenos-nicf team mailing list archive

Jak shodit IPC v revizi 939

 

Ahoj,
posilam patch na revizi 939, ktera shodi IPC komunikaci.

Honza
=== modified file 'boot/Makefile.common'
--- boot/Makefile.common	2011-05-01 19:00:40 +0000
+++ boot/Makefile.common	2011-08-30 21:00:32 +0000
@@ -91,6 +91,7 @@
 
 RD_SRVS_NON_ESSENTIAL = \
 	$(USPACE_PATH)/srv/bd/file_bd/file_bd \
+	$(USPACE_PATH)/srv/dma_srv/dma_srv \
 	$(USPACE_PATH)/srv/bd/part/guid_part/g_part \
 	$(USPACE_PATH)/srv/bd/part/mbr_part/mbr_part \
 	$(USPACE_PATH)/srv/clip/clip \
@@ -134,6 +135,7 @@
 
 RD_APPS_NON_ESSENTIAL = \
 	$(USPACE_PATH)/app/dltest/dltest \
+	$(USPACE_PATH)/app/dma_test/dma_test \
 	$(USPACE_PATH)/app/dltest2/dltest2 \
 	$(USPACE_PATH)/app/dload/dload \
 	$(USPACE_PATH)/app/edit/edit \

=== modified file 'uspace/Makefile'
--- uspace/Makefile	2011-05-01 12:33:18 +0000
+++ uspace/Makefile	2011-08-30 20:57:50 +0000
@@ -34,6 +34,7 @@
 
 DIRS = \
 	app/bdsh \
+	app/dma_test \
 	app/edit \
 	app/getterm \
 	app/init \
@@ -56,6 +57,7 @@
 	app/websrv \
 	app/sysinfo \
 	srv/clip \
+	srv/dma_srv \
 	srv/devmap \
 	srv/devman \
 	srv/loader \

=== added directory 'uspace/app/dma_test'
=== added file 'uspace/app/dma_test/Makefile'
--- uspace/app/dma_test/Makefile	1970-01-01 00:00:00 +0000
+++ uspace/app/dma_test/Makefile	2011-05-16 07:00:35 +0000
@@ -0,0 +1,34 @@
+
+# Copyright (c) 2010 Jan Zaloha
+#
+# 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.
+#
+
+USPACE_PREFIX = ../..
+BINARY = dma_test
+
+SOURCES = \
+	dma_test.c
+
+include $(USPACE_PREFIX)/Makefile.common
\ No newline at end of file

=== added file 'uspace/app/dma_test/dma_test.c'
--- uspace/app/dma_test/dma_test.c	1970-01-01 00:00:00 +0000
+++ uspace/app/dma_test/dma_test.c	2011-08-30 21:24:03 +0000
@@ -0,0 +1,209 @@
+/**
+ * @file
+ * @brief DMA testing process (should be removed in future).
+ */
+#include <stdio.h>
+#include <dma.h>
+#include <errno.h>
+#include <ipc/services.h>
+#include <ipc/ns.h>
+#include <async.h>
+
+#define NAME "DMA SERVER"
+
+#define TEST_MAX_AREAS 250
+#define LARGE_SIZE 30
+
+
+/**
+ * Tests sharing out DMA memory.
+ * @param[in] iid 	id of the call
+ * @param[in] icall	arguments of the call
+ *
+ */
+static void dma_connection_driver(ipc_callid_t iid, ipc_call_t *icall)
+{
+	async_answer_0(iid, EOK);
+	ipc_callid_t callid;
+	size_t size;
+
+	if (!async_share_in_receive(&callid, &size)) {
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+	size_t s = size / PAGE_SIZE;
+	//++s;
+
+	dma_mem_t dmt;
+
+	dmt.mapping_flags = AS_AREA_READ | AS_AREA_WRITE;
+	dmt.size = s;
+	int i;
+	i = dma_allocate_anonymous(&dmt, 0);
+
+
+	if (i != EOK) {
+		printf("Share starting failed with error %d\n", i);
+		async_answer_0(callid, ENOMEM);
+		exit(0);
+	}
+
+	async_share_in_finalize(callid, (void*) dmt.virtual, PROTO_READ
+	    | PROTO_WRITE);
+
+	printf("Share in succeded\n");
+	printf("All tests passed\n");
+	exit(0);
+
+}
+
+
+/**
+ * Tests many parallel shares to DMA server from two IDs
+ * @param[in] id connection server.
+ *
+ * @return EOK when success, otherwise error code.
+ */
+
+static int dma_test_server_many_shares_two(dma_srv_dev_id_t * id)
+{
+	dma_srv_dev_id_t id2;
+	dma_cli_register("dma_test/sever", &id2);
+	printf("sdfg\n");
+	void * areas[TEST_MAX_AREAS];
+	void * faddrs[TEST_MAX_AREAS];
+	int i;
+	size_t dummy_size;
+
+	for (i = 0; i < TEST_MAX_AREAS; ++i) {
+		size_t size = (3 * (i + 1));
+		void * addr = as_get_mappable_page(size * PAGE_SIZE);
+		if ((areas[i] = as_area_create(addr, size * PAGE_SIZE, AS_AREA_READ
+		    | AS_AREA_WRITE)) == NULL) {
+			return ENOMEM;
+		}
+		printf("a\n");
+	}
+	int rc = 0;
+	for (i = 0; i < TEST_MAX_AREAS; ++i) {
+		printf("b\n");
+		if ((rc = dma_cli_set_ownership(areas[i], i + 1, i + 1, AS_AREA_READ
+		    | AS_AREA_WRITE, id))) {
+			return rc;
+		}
+		if ((rc = dma_cli_set_ownership(areas[i], i + 1, i + 1, AS_AREA_READ
+		    | AS_AREA_WRITE, &id2))) {
+			return rc;
+		}
+		printf("asdfds\n");
+		dma_lock((void*) (((uintptr_t) areas[i]) + (i + 1) * PAGE_SIZE),
+		    &faddrs[i], 1, &dummy_size);
+	}
+
+	for (i = 0; i < TEST_MAX_AREAS; ++i) {
+		if ((rc = dma_cli_clear_ownership(faddrs[i], id))) {
+			as_area_destroy(areas[i]);
+			return rc;
+		}
+	}
+	if (dma_cli_unregister(&id2) == EOK) {
+		return EINVAL;
+	}
+
+	if ((rc = dma_cli_cleanup(&id2)) != EOK) {
+		return rc;
+	}
+
+	if ((rc = dma_cli_unregister(&id2)) != EOK) {
+		return rc;
+	}
+
+	return EOK;
+
+}
+
+
+/**
+ * Tests many parallel shares to DMA server.
+ * @param[in] id connection server.
+ *
+ * @return EOK when success, otherwise error code.
+ */
+static int dma_test_server_many_shares(dma_srv_dev_id_t * id)
+{
+	void * areas[TEST_MAX_AREAS];
+	int i;
+	for (i = 0; i < TEST_MAX_AREAS; ++i) {
+		size_t size = (3 * (i + 1));
+		void * addr = as_get_mappable_page(size * PAGE_SIZE);
+		if ((areas[i] = as_area_create(addr, size * PAGE_SIZE, AS_AREA_READ
+		    | AS_AREA_WRITE)) == NULL) {
+			return ENOMEM;
+		}
+	}
+	int rc = 0;
+	for (i = 0; i < TEST_MAX_AREAS; ++i) {
+		if ((rc = dma_cli_set_ownership(areas[i], i + 1, i + 1, AS_AREA_READ
+		    | AS_AREA_WRITE, id))) {
+			return rc;
+		}
+		as_area_destroy(areas[i]);
+		uspace_dma_print("Iteration %d\n", i);
+	}
+	return dma_cli_cleanup(id);
+
+}
+
+
+/**
+ * Handling procedure for sharing memory out
+ */
+static void dma_connection(ipc_callid_t iid, ipc_call_t *icall)
+{
+	switch ((sysarg_t)(IPC_GET_ARG1(*icall))) {
+	case DMA_SHARE:
+		dma_connection_driver(iid, icall);
+		break;
+
+	default:
+		/* No such interface */
+		async_answer_0(iid, ENOENT);
+	}
+
+}
+
+dma_mem_t dmt;
+int main(void)
+{
+	dma_srv_dev_id_t id;
+	int rc;
+	printf("%d\n", dma_allocator_init());
+	dma_cli_register("dma_test/server", &id);
+	printf("%d\n", (int) id.id);
+	dma_cli_cleanup(&id);
+	printf("%d\n", (int) id.id);
+	if ((rc = dma_test_server_many_shares_two(&id))) {
+		printf("DMA test server many shares two failed with code %d\n", rc);
+	} else {
+		printf("DMA test server many shares two succeeded\n");
+	}
+
+	if ((rc = dma_test_server_many_shares(&id))) {
+		printf("DMA test server many shares failed with code %d\n", rc);
+	} else {
+		printf("DMA test server many shares succeeded\n");
+	}
+
+
+	dma_cli_cleanup(&id);
+	async_set_client_connection(dma_connection);
+
+	if (service_register(1000) != EOK) {
+		printf("Failed registering as a service.\n");
+		return -1;
+	}
+	printf("Entering share in stage, run dma_clie\n");
+	async_manager();
+
+	return 0;
+}

=== modified file 'uspace/app/init/init.c'
--- uspace/app/init/init.c	2011-03-31 18:22:14 +0000
+++ uspace/app/init/init.c	2011-08-30 21:10:10 +0000
@@ -274,6 +274,7 @@
 #ifdef CONFIG_START_DEVMAN
 	spawn("/srv/devman");
 #endif
+	//spawn("/srv/dma_srv");
 	spawn("/srv/apic");
 	spawn("/srv/i8259");
 	spawn("/srv/fhc");

=== modified file 'uspace/lib/c/Makefile'
--- uspace/lib/c/Makefile	2011-05-01 19:00:40 +0000
+++ uspace/lib/c/Makefile	2011-08-30 20:53:27 +0000
@@ -78,6 +78,8 @@
 	generic/fibril.c \
 	generic/fibril_synch.c \
 	generic/pcb.c \
+	generic/adt/avltree_generic.c \
+	generic/dma.c \
 	generic/smc.c \
 	generic/thread.c \
 	generic/tls.c \

=== added file 'uspace/lib/c/generic/adt/avltree_generic.c'
--- uspace/lib/c/generic/adt/avltree_generic.c	1970-01-01 00:00:00 +0000
+++ uspace/lib/c/generic/adt/avltree_generic.c	2011-08-24 08:58:33 +0000
@@ -0,0 +1,932 @@
+/*
+ * Copyright (c) 2011 Radim Vansa, Jan Zaloha
+ * 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.
+ */
+
+/** @addtogroup genericadt
+ * @{
+ */
+
+/**
+ * @file
+ * @brief generic avltree implementation.
+ *
+ * This file implements avltree type and operations. It is a bit slower than hardcoded avltree, but
+ * it is much powerful. User can search by specified condition in the tree, not only to equal.
+ *
+ * The avltree has the following properties:
+ * @li it is a ballanced binary tree
+ * @li each node in tree has the property, that distinction of depth of left and right subtree is at most 1
+ * @li values are stored in all nodes
+ *
+ */
+
+#include "adt/avltree_generic.h"
+#ifdef KERNEL
+#include "print.h"
+#else
+#include <stdio.h>
+#endif
+
+#define COND_PAR_SET(x, y) if ((x) != NULL) {(x)->parent = y;}
+#define A_HIGH_SET_PARENT \
+    if (a->parent == NULL){ \
+        tree->root = b; \
+    } else { \
+        if (a->parent->left_son == a) { \
+            a->parent->left_son = b; \
+        } else { \
+            a->parent->right_son = b; \
+        } \
+    }
+#define B_HIGH_SET_PARENT \
+    if (b->parent == NULL){ \
+        tree->root = a; \
+    } else { \
+        if (b->parent->left_son == b) { \
+            b->parent->left_son = a; \
+        } else { \
+            b->parent->right_son = a; \
+        } \
+    }
+
+/**
+ *  Function for swapping nodes.
+ *  @param tree tree, where swapping is done
+ *  @param a first node to swap
+ *  @param b second node to swap
+ */
+static void _swap_nodes(avltree_gen_t *tree, avltree_gen_node_t *a,
+    avltree_gen_node_t *b)
+{
+	avltree_gen_node_t *a_parent = a->parent;
+	avltree_gen_node_t *a_left = a->left_son;
+	avltree_gen_node_t *a_right = a->right_son;
+	avltree_gen_node_t *b_parent = b->parent;
+	avltree_gen_node_t *b_left = b->left_son;
+	avltree_gen_node_t *b_right = b->right_son;
+	SWAP(a->balance, b->balance);
+	if (a_left == b) {
+		a->right_son = b_right;
+		COND_PAR_SET(b_right, a);
+		a->left_son = b_left;
+		COND_PAR_SET(b_left, a);
+		b->left_son = a;
+		b->right_son = a_right;
+		COND_PAR_SET(a_right, b);
+		A_HIGH_SET_PARENT;
+		a->parent = b;
+		b->parent = a_parent;
+		return;
+	}
+	if (a_right == b) {
+		a->left_son = b_left;
+		COND_PAR_SET(b_left, a);
+		a->right_son = b_right;
+		COND_PAR_SET(b_right, a);
+		b->left_son = a_left;
+		COND_PAR_SET(a_left, b);
+		b->right_son = a;
+		A_HIGH_SET_PARENT;
+		a->parent = b;
+		b->parent = a_parent;
+		return;
+	}
+	if (b_left == a) {
+		b->left_son = a_left;
+		COND_PAR_SET(a_left, b);
+		b->right_son = a_right;
+		COND_PAR_SET(a_right, b);
+		a->left_son = b;
+		a->right_son = b_right;
+		COND_PAR_SET(b_right, a);
+		B_HIGH_SET_PARENT;
+		b->parent = a;
+		a->parent = b_parent;
+		return;
+	}
+	if (b_right == a) {
+		b->left_son = a_left;
+		COND_PAR_SET(a_left, b);
+		b->right_son = a_right;
+		COND_PAR_SET(a_right, b);
+		a->left_son = b_left;
+		COND_PAR_SET(b_left, a);
+		a->right_son = b;
+		B_HIGH_SET_PARENT;
+		b->parent = a;
+		a->parent = b_parent;
+		return;
+	}
+	// no relation
+	a->left_son = b_left;
+	COND_PAR_SET(b_left, a);
+	a->right_son = b_right;
+	COND_PAR_SET(b_right, a);
+	b->left_son = a_left;
+	COND_PAR_SET(a_left, b);
+	b->right_son = a_right;
+	COND_PAR_SET(a_right, b);
+	A_HIGH_SET_PARENT;
+	B_HIGH_SET_PARENT;
+	a->parent = b_parent;
+	b->parent = a_parent;
+}
+
+/**
+ * Does right rotation on node. Do NOT call this procedure from outside.
+ *
+ * @param input_tree Pointer to AVL tree where the rotation is proceeded.
+ * @param actual_node Pointer to node of tree, which is root of rotated subtree.
+ *
+ * @return Pointer to new root of rotated subtree.
+ */
+
+static avltree_gen_node_t * right_rotation(avltree_gen_t * input_tree,
+    avltree_gen_node_t * actual_node)
+{
+	/*
+	 * Left son of root will be new root.
+	 */
+	avltree_gen_node_t * new_root = actual_node->left_son;
+	/*
+	 * We should remember parent of old root to change pointer
+	 * to its corresponding subtree.
+	 */
+	avltree_gen_node_t * temp_parent = actual_node->parent;
+	/*
+	 * Right son of left son of old root of subtree will be reconected.
+	 */
+	avltree_gen_node_t * rejoined_node = actual_node->left_son->right_son;
+	/*
+	 * Reconnecting pointers.
+	 */
+	new_root->parent = temp_parent;
+	new_root->right_son = actual_node;
+	actual_node->parent = new_root;
+	actual_node->left_son = rejoined_node;
+
+	/*
+	 * If rejoined subtree isn't empty, we should correct it's parent.
+	 */
+	if (rejoined_node != NULL) {
+		rejoined_node->parent = actual_node;
+	}
+	/*
+	 * If we are at root of all tree, set new root.
+	 * In other case correct the corresponding pointer from parent.
+	 */
+	if (new_root->parent == NULL) {
+		input_tree->root = new_root;
+	} else {
+		if (new_root->parent->left_son == actual_node) {
+			new_root->parent->left_son = new_root;
+		} else {
+			new_root->parent->right_son = new_root;
+		}
+	}
+	return new_root;
+}
+
+/**
+ * Does left rotation on node. Do NOT call this procedure from outside.
+ *
+ * @param input_tree Pointer to AVL tree where the rotation is proceeded.
+ * @param actual_node Pointer to node of tree, which is root of rotated subtree.
+ *
+ * @return Pointer to new root of rotated subtree.
+ */
+static avltree_gen_node_t * left_rotation(avltree_gen_t * input_tree,
+    avltree_gen_node_t * actual_node)
+{
+	/*
+	 * Right son of root will be new root.
+	 */
+	avltree_gen_node_t * new_root = actual_node->right_son;
+	/*
+	 * We should remember parent of old root to change pointer
+	 * to its corresponding subtree.
+	 */
+	avltree_gen_node_t * temp_parent = actual_node->parent;
+	/*
+	 * Left son of right son of old root of subtree will be reconected.
+	 */
+	avltree_gen_node_t * rejoined_node = actual_node->right_son->left_son;
+	/*
+	 * Reconnecting pointers.
+	 */
+	actual_node->parent = new_root;
+	new_root->parent = temp_parent;
+	new_root->left_son = actual_node;
+	actual_node->right_son = rejoined_node;
+
+	/*
+	 * If rejoined subtree isn't empty, we should correct it's parent.
+	 */
+	if (rejoined_node != NULL) {
+		rejoined_node->parent = actual_node;
+	}
+	/*
+	 * If we are at root of all tree, set new root.
+	 * In other case correct the corresponding pointer from parent.
+	 */
+	if (new_root->parent == NULL) {
+		input_tree->root = new_root;
+	} else {
+		if (new_root->parent->left_son == actual_node) {
+			new_root->parent->left_son = new_root;
+		} else {
+			new_root->parent->right_son = new_root;
+		}
+	}
+	return new_root;
+}
+
+static avltree_gen_node_t * subst_deleted_node(avltree_gen_t *source,
+    avltree_gen_node_t * input_node)
+{
+	while (RIGHT_LIGHTER) {
+		/*
+		 * If node is leaf, just return pointer to it.
+		 */
+		if (input_node->left_son == NULL && input_node->right_son == NULL) {
+			return input_node;
+		}
+		/*
+		 * If node has only right son, find the most left node in it's subtree, save value
+		 * from it to root of subtree and do the same thing on it.
+		 */
+		else if (input_node->left_son == NULL) {
+			avltree_gen_node_t * deleted = input_node->right_son;
+			while (deleted->left_son != NULL) {
+				deleted = deleted->left_son;
+			}
+			_swap_nodes(source, input_node, deleted);
+			continue;
+			/*
+			 * If node has only left son, find the most right node in it's subtree, save value
+			 * from it to root of subtree and do the same thing on it.
+			 */
+		} else if (input_node->right_son == NULL) {
+			avltree_gen_node_t * deleted = input_node->left_son;
+			while (deleted->right_son != NULL) {
+				deleted = deleted->right_son;
+			}
+			_swap_nodes(source, input_node, deleted);
+			//input_node=deleted;
+			continue;
+		} else {
+			/*
+			 * If node has both sons, find the most right node in it's left subtree, save value
+			 * from it to root and do the same thing on it.
+			 */
+			avltree_gen_node_t * deleted = input_node->left_son;
+			while (deleted->right_son != NULL) {
+				deleted = deleted->right_son;
+			}
+			_swap_nodes(source, input_node, deleted);
+			//input_node=deleted;
+			continue;
+		}
+	}
+}
+
+/**
+ * Fixes balancing condition after removal of a node from AVL tree.
+ * Do NOT call from outside.
+ *
+ * @param input_tree Pointer to tree, from which was a node removed.
+ * @param actual_node Pointer to node, where should be the AVL condition fixed.
+ */
+static void avltree_gen_fix_remove(avltree_gen_t * input_tree,
+    avltree_gen_node_t * actual_node)
+{
+
+	while (RIGHT_LIGHTER) {
+		if (actual_node->balance == RIGHT_TOO_LIGHT) {
+			if (actual_node->left_son->balance == RIGHT_LIGHTER) {
+				avltree_gen_node_t * new_root = right_rotation(input_tree,
+				    actual_node);
+				new_root->right_son->balance = BALANCED;
+				new_root->balance = BALANCED;
+				if (new_root->parent != NULL) {
+					if (new_root->parent->left_son == new_root) {
+						--new_root->parent->balance;
+					} else {
+						++new_root->parent->balance;
+					}
+					actual_node = new_root->parent;
+					continue;
+				} else {
+					return;
+				}
+			}
+			if (actual_node->left_son->balance == BALANCED) {
+				avltree_gen_node_t * new_root = right_rotation(input_tree,
+				    actual_node);
+				new_root->right_son->balance = RIGHT_LIGHTER;
+				new_root->balance = LEFT_LIGHTER;
+				return;
+			}
+			if (actual_node->left_son->balance == LEFT_LIGHTER) {
+				int post_balance;
+				avltree_gen_node_t * new_root;
+				if (actual_node->left_son->right_son->balance == LEFT_LIGHTER) {
+					post_balance = LEFT_LIGHTER;
+				} else if (actual_node->left_son->right_son->balance
+				    == BALANCED) {
+					post_balance = BALANCED;
+				} else {
+					post_balance = RIGHT_LIGHTER;
+				}
+				left_rotation(input_tree, actual_node->left_son);
+				new_root = right_rotation(input_tree, actual_node);
+				new_root->balance = BALANCED;
+				if (post_balance == RIGHT_LIGHTER) {
+					new_root->left_son->balance = BALANCED;
+					new_root->right_son->balance = LEFT_LIGHTER;
+				} else if (post_balance == BALANCED) {
+					new_root->left_son->balance = BALANCED;
+					new_root->right_son->balance = BALANCED;
+				} else {
+					new_root->left_son->balance = RIGHT_LIGHTER;
+					new_root->right_son->balance = BALANCED;
+				}
+				if (new_root->parent == NULL) {
+					return;
+				}
+				if (new_root->parent->left_son == new_root) {
+					--new_root->parent->balance;
+				} else {
+					++new_root->parent->balance;
+				}
+				actual_node = new_root->parent;
+				continue;
+			}
+		}
+		if (actual_node->balance == (LEFT_TOO_LIGHT)) {
+			if (actual_node->right_son->balance == LEFT_LIGHTER) {
+				avltree_gen_node_t * new_root = left_rotation(input_tree,
+				    actual_node);
+				new_root->left_son->balance = BALANCED;
+				new_root->balance = BALANCED;
+				if (new_root->parent != NULL) {
+					if (new_root->parent->left_son == new_root) {
+						--new_root->parent->balance;
+					} else {
+						++new_root->parent->balance;
+					}
+					actual_node = new_root->parent;
+					continue;
+				} else {
+					return;
+				}
+
+			}
+			if (actual_node->right_son->balance == BALANCED) {
+				avltree_gen_node_t * new_root = left_rotation(input_tree,
+				    actual_node);
+				new_root->left_son->balance = LEFT_LIGHTER;
+				new_root->balance = RIGHT_LIGHTER;
+				return;
+			}
+			if (actual_node->right_son->balance == RIGHT_LIGHTER) {
+				int post_balance;
+				avltree_gen_node_t * new_root;
+				if (actual_node->right_son->left_son->balance == LEFT_LIGHTER) {
+					post_balance = LEFT_LIGHTER;
+				} else if (actual_node->right_son->left_son->balance
+				    == BALANCED) {
+					post_balance = BALANCED;
+				} else {
+					post_balance = RIGHT_LIGHTER;
+				}
+				right_rotation(input_tree, actual_node->right_son);
+				new_root = left_rotation(input_tree, actual_node);
+				new_root->balance = BALANCED;
+				if (post_balance == RIGHT_LIGHTER) {
+					new_root->left_son->balance = BALANCED;
+					new_root->right_son->balance = LEFT_LIGHTER;
+				} else if (post_balance == BALANCED) {
+					new_root->left_son->balance = BALANCED;
+					new_root->right_son->balance = BALANCED;
+				} else {
+					new_root->left_son->balance = RIGHT_LIGHTER;
+					new_root->right_son->balance = BALANCED;
+				}
+				if (new_root->parent == NULL) {
+					return;
+				}
+				if (new_root->parent->left_son == new_root) {
+					--new_root->parent->balance;
+				} else {
+					++new_root->parent->balance;
+				}
+				actual_node = new_root->parent;
+				continue;
+			}
+
+		}
+		if (actual_node->parent == NULL) {
+			return;
+		}
+		if (actual_node->balance == RIGHT_LIGHTER || actual_node->balance
+		    == LEFT_LIGHTER) {
+			return;
+		}
+		if (actual_node->balance == BALANCED) {
+			if (actual_node->parent->left_son == actual_node) {
+				--actual_node->parent->balance;
+			} else {
+				++actual_node->parent->balance;
+			}
+			actual_node = actual_node->parent;
+			continue;
+		}
+	}
+}
+
+/**
+ * This function does balancing. Do NOT call it from outside.
+ *
+ * @param input_tree Pointer to target AVL tree, where is the balancing processed.
+ * @param actual_node Pointer to node, which was inserted and from where the balacing
+ *               process should be started (parent of inserted node).
+ *               This node should have correct balancing information according
+ *               the depth of it's subtrees.
+ */
+
+static void avltree_gen_fix_add(avltree_gen_t * input_tree,
+    avltree_gen_node_t * actual_node)
+{
+	/*
+	 *      First we watch, whether we should send the balancing information
+	 *      upwards.
+	 */
+	while (actual_node->balance == RIGHT_LIGHTER || actual_node->balance
+	    == LEFT_LIGHTER) {
+		/*
+		 * If we reached the top of the tree, stop.
+		 */
+		if (actual_node->parent == NULL) {
+			return;
+		}
+		/*
+		 * Fix balance info of actual node's parent.
+		 */
+		if (actual_node->parent->left_son == actual_node) {
+			++actual_node->parent->balance;
+		} else {
+			--actual_node->parent->balance;
+		}
+		/*
+		 * Rise one level upwards.
+		 */
+		actual_node = actual_node->parent;
+	}
+	/*
+	 * If this level is perfectly balanced, no action needed, stop.
+	 */
+	if (actual_node->balance == BALANCED) {
+		return;
+	}
+
+	/*
+	 * This code balances the tree.
+	 */
+	if (actual_node->balance == RIGHT_TOO_LIGHT) {
+		if (actual_node->left_son->balance == RIGHT_LIGHTER) {
+			avltree_gen_node_t * new_root = right_rotation(input_tree,
+			    actual_node);
+			new_root->balance = BALANCED;
+			new_root->right_son->balance = BALANCED;
+			return;
+		} else {
+			int post_balancing;
+			avltree_gen_node_t * new_root;
+			if (actual_node->left_son->right_son->balance > BALANCED) {
+				post_balancing = RIGHT_LIGHTER;
+			} else {
+				if (actual_node->left_son->right_son->balance == BALANCED) {
+					post_balancing = BALANCED;
+				} else {
+					post_balancing = LEFT_LIGHTER;
+				}
+			}
+			left_rotation(input_tree, actual_node->left_son);
+			new_root = right_rotation(input_tree, actual_node);
+			new_root->balance = BALANCED;
+			if (post_balancing == RIGHT_LIGHTER) {
+				new_root->left_son->balance = BALANCED;
+				new_root->right_son->balance = LEFT_LIGHTER;
+			} else {
+				if (post_balancing == BALANCED) {
+					new_root->left_son->balance = BALANCED;
+					new_root->right_son->balance = BALANCED;
+				} else {
+					new_root->left_son->balance = RIGHT_LIGHTER;
+					new_root->right_son->balance = BALANCED;
+				}
+			}
+		}
+	} else {
+		if (actual_node->right_son->balance == LEFT_LIGHTER) {
+			avltree_gen_node_t * new_root = left_rotation(input_tree,
+			    actual_node);
+			new_root->balance = BALANCED;
+			new_root->left_son->balance = BALANCED;
+		} else {
+			int post_balancing;
+			avltree_gen_node_t * new_root;
+			if (actual_node->right_son->balance == BALANCED) {
+				//int * p=BALANCED;
+				//(*p);
+			}
+			if (actual_node->right_son->left_son->balance > BALANCED) {
+				post_balancing = RIGHT_LIGHTER;
+			} else {
+				if (actual_node->right_son->left_son->balance == BALANCED) {
+					post_balancing = BALANCED;
+				} else {
+					post_balancing = LEFT_LIGHTER;
+				}
+			}
+			right_rotation(input_tree, actual_node->right_son);
+			new_root = left_rotation(input_tree, actual_node);
+			new_root->balance = BALANCED;
+			if (post_balancing == RIGHT_LIGHTER) {
+				new_root->left_son->balance = BALANCED;
+				new_root->right_son->balance = LEFT_LIGHTER;
+			} else {
+				if (post_balancing == BALANCED) {
+					new_root->left_son->balance = BALANCED;
+					new_root->right_son->balance = BALANCED;
+				} else {
+					new_root->left_son->balance = RIGHT_LIGHTER;
+					new_root->right_son->balance = BALANCED;
+				}
+			}
+		}
+	}
+}
+
+/**
+ * Initializes AVL tree structure, it corresponds  with constructor
+ *
+ * @param input_tree Pointer to initialized structure
+ * @param cmp Pointer to function, which compares two pointers to structure inserted
+ *		 into the tree. It should return LEFT_LIGHTER when the first its argument is less then
+ *		 the second, RIGHT_LIGHTER when inits first argument is greater then second and BALANCED when
+ *		 they are equal.
+ */
+void avltree_gen_init(avltree_gen_t * input_tree, int(*cmp)(void*, void*))
+{
+	input_tree->root = NULL;
+	input_tree->compare_keys = cmp;
+}
+
+/**
+ * Initializes new node inserted into AVL tree. Do NOT call it from outside.
+ *
+ * @param input_node Pointer to initialized node.
+ * @param key Key, which should be assigned to node.
+ */
+void avltree_gen_node_init(avltree_gen_node_t * input_node, void *key)
+{
+	input_node->balance = BALANCED;
+	input_node->key = key;
+	input_node->left_son = NULL;
+	input_node->right_son = NULL;
+	input_node->parent = NULL;
+}
+
+/**
+ * Inserts new value to AVL tree and automatically does balancing.
+ *
+ * @param input_tree Pointer to AVL tree, where the value is inserted.
+ * @param new_node Pointer to inserted value.
+ *
+ * @return When the function successes, it returns pointer equal to second
+ parameter, when it fails, it returns NULL pointer.
+ */
+void avltree_gen_insert(avltree_gen_t * input_tree,
+    avltree_gen_node_t *new_node)
+{
+	avltree_gen_node_t * actual = input_tree->root;
+	avltree_gen_node_t * parent = NULL;
+	if (input_tree->root == NULL) {
+		input_tree->root = new_node;
+		return;
+	}
+	while (actual != NULL) {
+		parent = actual;
+		if (input_tree->compare_keys(new_node->key, actual->key) < BALANCED) {
+			actual = actual->left_son;
+		} else {
+			actual = actual->right_son;
+		}
+	}
+
+	if (input_tree->compare_keys(new_node->key, parent->key) < BALANCED) {
+		parent->left_son = new_node;
+		++parent->balance;
+	} else {
+		parent->right_son = new_node;
+		--parent->balance;
+	}
+	new_node->parent = parent;
+	avltree_gen_fix_add(input_tree, new_node->parent);
+	return;
+}
+
+/**
+ * DEBUG funtion.
+ */
+void avltree_gen_traverse(const avltree_gen_node_t * a, unsigned int tabs)
+{
+	if (a == NULL) {
+		return;
+	}
+	if (a == (void *) 0x800F61B0) {
+		printf("\nL%p R%p\n", a->left_son, a->right_son);
+	}
+	avltree_gen_traverse(a->left_son, tabs + 1);
+	//i=a->data;
+	unsigned int i;
+	for (i = 0; i < tabs; ++i) {
+		printf("%c", ' ');
+	}
+	printf("%p\n", a->key);
+	avltree_gen_traverse(a->right_son, tabs + 1);
+}
+
+/**
+ * Finds pointer to first data structure in AVL tree, which corresponds to
+ * the key.
+ *
+ * @param source Pointer to ALV tree, where is the pointer founded.
+ * @param key Pointer to key, which is searched.
+ *
+ * @return If the procedure successes, it returns pointer to founded structure.
+ *		  If it fails, it returns NULL pointer.
+ */
+avltree_gen_node_t * avltree_gen_find(avltree_gen_t * source, void * key)
+{
+	avltree_gen_node_t * actual = source->root;
+	while (actual != NULL && source->compare_keys(key, actual->key) != BALANCED) {
+		if (source->compare_keys(key, actual->key) < BALANCED) {
+			actual = actual->left_son;
+		} else {
+			actual = actual->right_son;
+		}
+	}
+	return actual;
+}
+
+/**
+ * Finds pointer to first data structure in AVL tree, which corresponds to
+ * the key.
+ *
+ * @param source Pointer to ALV tree, where is the pointer founded.
+ * @param key Pointer to key, which is searched.
+ * @param cmp Pointer to function used when the tree is traversed, which compares pointers to key and
+ *               to structure inserted into the tree. It should return LEFT_LIGHTER when the first its
+ *               argument is less then the second, RIGHT_LIGHTER when first argument is greater then
+ *               second and BALANCED when they are equal.
+ *
+ * @return If the procedure successes, it returns pointer to found structure.
+ *                If it fails, it returns NULL pointer.
+ */
+avltree_gen_node_t * avltree_gen_find_parametrized(avltree_gen_t * source,
+    void * key, int(*cmp)(void*, void*))
+{
+	avltree_gen_node_t * actual = source->root;
+	while (actual != NULL && cmp(key, actual->key) != BALANCED) {
+		if (cmp(key, actual->key) < BALANCED) {
+			actual = actual->left_son;
+		} else {
+			actual = actual->right_son;
+		}
+	}
+	return actual;
+}
+
+/**
+ * This procedure tries to drop first AVL tree node corresponding to key from the tree.
+ *
+ * @param source Pointer to AVL tree structure, from which is the node deleted.
+ * @param key Pointer to key, which should be dropped
+ *
+ * @return If the procedure successes, it returns pointer to structure removed from tree.
+ *		  If it fails, it returns NULL pointer.
+ */
+avltree_gen_node_t * avltree_gen_drop(avltree_gen_t * source, void * key)
+{
+	/*
+	 * First we find the corresponding node. If it doesn't exist, return NULL.
+	 */
+	avltree_gen_node_t * ret_val_node = avltree_gen_find(source, key);
+	if (ret_val_node == NULL) {
+		return NULL;
+	}
+
+	return avltree_gen_rem_node(source, ret_val_node);
+
+}
+
+/**
+ * This procedure tries to drop first AVL tree node corresponding to key from the tree.
+ *
+ * @param source Pointer to AVL tree structure, from which is the node deleted.
+ * @param key Pointer to key, which should be dropped
+ * @param cmp Pointer to function used when the tree is traversed, which compares pointers to key and
+ *               to structure inserted into the tree. It should return LEFT_LIGHTER when the first its
+ *               argument is less then the second, RIGHT_LIGHTER when first argument is greater then
+ *               second and BALANCED when they are equal.
+ *
+ * @return If the procedure successes, it returns pointer to structure removed from tree.
+ *                If it fails, it returns NULL pointer.
+ */
+avltree_gen_node_t * avltree_gen_drop_parametrized(avltree_gen_t * source,
+    void * key, int(*cmp)(void*, void*))
+{
+	/*
+	 * First we find the corresponding node. If it doesn't exist, return NULL.
+	 */
+	avltree_gen_node_t * ret_val_node = avltree_gen_find_parametrized(source,
+	    key, cmp);
+	if (ret_val_node == NULL) {
+		return NULL;
+	}
+
+	return avltree_gen_rem_node(source, ret_val_node);
+}
+
+/**
+ * This procedure tries to drop first AVL tree node corresponding to key from the tree.
+ *
+ * @param source Pointer to AVL tree structure, from which is the node deleted.
+ * @param key Pointer to key, which should be dropped
+
+ * @return If the procedure successes, it returns pointer to structure removed from tree.
+ *                If it fails, it returns NULL pointer.
+ */
+
+avltree_gen_node_t * avltree_gen_rem_node(avltree_gen_t * source,
+    avltree_gen_node_t * node)
+{
+
+	avltree_gen_node_t * ret_val_node = node;
+
+	/*
+	 * Remember pointer to contained data and transform problem to removal of a leaf.
+	 */
+
+	subst_deleted_node(source, ret_val_node);
+
+	/*
+	 * If the leaf is root, just empty the tree.
+	 * In other case disconnect the leaf from tree and run balancing procedure.
+	 */
+	if (ret_val_node->parent == NULL) {
+		source->root = NULL;
+	} else {
+		if (ret_val_node->parent->left_son == ret_val_node) {
+			--(ret_val_node->parent->balance);
+			ret_val_node->parent->left_son = NULL;
+		} else {
+			++(ret_val_node->parent->balance);
+			ret_val_node->parent->right_son = NULL;
+		}
+		avltree_gen_fix_remove(source, ret_val_node->parent);
+	}
+
+	ret_val_node->balance = BALANCED;
+	ret_val_node->left_son = NULL;
+	ret_val_node->right_son = NULL;
+	ret_val_node->parent = NULL;
+	return ret_val_node;
+}
+
+/**
+ * Converts problem of deleting ordinal node in AVL tree to problem of
+ * deleting leaf. Could be launched on ordinal BST. Do NOT call from outside.
+ *
+ * @param node Node which is chosen to be deleted
+ *
+ * @return Pointer to real node, which will be deleted
+ */
+static inline void _print_node(avltree_gen_node_t *node)
+{
+	printf("N: %p, P: %p, L: %p, R: %p\n", node, node->parent, node->left_son,
+	    node->right_son);
+}
+
+int avltree_gen_test_cond(avltree_gen_t * input)
+{
+	if (input->root == NULL) {
+		return RIGHT_LIGHTER;
+	}
+
+	return avltree_gen_test(input->root);
+}
+
+/**
+ * Prints value handled by node and it's subtree.
+ * @param node poiter to node to be printed
+ * @param printer pointer to printer function
+ */
+static void avltree_print_node_gen(avltree_gen_node_t * node, void(*printer)(
+    void*))
+{
+	if (node == NULL) {
+		return;
+	}
+
+	avltree_print_node_gen(node->left_son, printer);
+	printer(node->key);
+	avltree_print_node_gen(node->right_son, printer);
+
+}
+
+/**
+ * Traverses and prints sorted values from avl tree.
+ * @param source poiter to tree to be traversed and printed
+ * @param printer pointer to printer function
+ */
+
+void avltree_gen_print_parametrized(avltree_gen_t * source, void(*printer)(
+    void*))
+{
+	avltree_print_node_gen(source->root, printer);
+}
+
+/**
+ * Returns the most left node in AVL tree
+ * @param source pointer to traversed tree
+ * 
+ * @return	NULL on empty tree, otherwise pointer to node with least key
+ * 		value in default comparision
+ */
+avltree_gen_node_t * avltree_gen_get_min(avltree_gen_t * source)
+{
+	avltree_gen_node_t * actual = source->root;
+	avltree_gen_node_t * parent = NULL;
+
+	while (actual != NULL) {
+		parent = actual;
+		actual = actual->left_son;
+	}
+	return parent;
+}
+
+/**
+ * avltree_gen_tests AVL tree condition (subtraction of depths of subtrees is not
+ * bigger than one) for specified AVL tree. If the condition is not
+ * passed writes "ERROR" to console.
+ * 
+ * @param input avltree_gen_tested tree root.
+ * 
+ * @return 
+ */
+int avltree_gen_test(avltree_gen_node_t * input)
+{
+	int right_subtree;
+	int left_subtree;
+	if (input == NULL) {
+		return BALANCED;
+	}
+	right_subtree = avltree_gen_test(input->right_son);
+	left_subtree = avltree_gen_test(input->left_son);
+	if (left_subtree - right_subtree - input->balance != BALANCED) {
+		puts("ERROR");
+	}
+	if (left_subtree > right_subtree) {
+		return left_subtree + RIGHT_LIGHTER;
+	} else {
+		return right_subtree + RIGHT_LIGHTER;
+	}
+}

=== added file 'uspace/lib/c/generic/dma.c'
--- uspace/lib/c/generic/dma.c	1970-01-01 00:00:00 +0000
+++ uspace/lib/c/generic/dma.c	2011-08-30 21:23:03 +0000
@@ -0,0 +1,278 @@
+/*
+ * Copyright (c) 2011 Jan Zaloha
+ * 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 <ddi.h>
+#include <dma.h>
+#include <errno.h>
+#include <libc.h>
+#include <ipc/ns.h>
+#include <ipc/services.h>
+#include <async.h>
+#include <str.h>
+/** @addtogroup dma_userspace
+ * @{
+ */
+
+/**
+ * @file
+ * @brief DMA related standard library functions
+ */
+
+static int dma_srv_phone = -1;
+
+/**
+ * Highlevel interface of DMA allocator
+ *
+ * @param[out] pphys_addr	pointer to memory, where should be placed address of begin of physical memory block
+ * @param[in] virt_addr		pointer to virtual memory area, where should be allocated memory mapped
+ * @param[out] handle		pointer to memory, where should be placed handle to allocated object
+ *                          -required, but unused, will be filled with 0
+ * @param[in] pages			number of pages to be allocated (only supported value is 1)
+ * @param[in] flags1		flags same as flags for as_area_create
+ * @param[in] flags2		flags for searching free block, should be 0
+ *
+ * @return on success EOK, otherwise proper errno value
+ */
+int dma_allocate(void ** pphys_addr, void * virt_addr, unsigned long pages,
+    int flags1, int flags2)
+{
+	return EOK;
+}
+/**
+ * Registers client with server
+ * @param[in] client_identifier	systemwide unique identifier
+ * @param[out] id				 id of the device
+ * @return  according to dma_srv_register
+ */
+int dma_cli_register(const char * client_identifier, dma_srv_dev_id_t * id)
+{
+	size_t size = str_length(client_identifier) + 1;
+	int rc2;
+	sysarg_t rc1;
+	ipc_call_t answer;
+
+	if (dma_srv_phone < 0) {
+		return EPARTY;
+	}
+	aid_t req = async_send_0(dma_srv_phone, DMA_SRV_REGISTER, &answer);
+	rc2 = async_data_write_start(dma_srv_phone, client_identifier, size);
+	async_wait_for(req, &rc1);
+	if (rc1 != EOK || rc2 != EOK) {
+		return rc1;
+		id->id = 0;
+	}
+
+	(id->id) = IPC_GET_ARG1(answer);
+	uspace_dma_print("ID = %d\n", (int) (id->id));
+	return EOK;
+}
+
+/**
+ * Unegisters client with server
+ * @param[in] id id of the device
+ * @return  according to dma_srv_unregister
+ */
+int dma_cli_unregister(dma_srv_dev_id_t * id)
+{
+	sysarg_t rc1;
+	ipc_call_t answer;
+
+	if (dma_srv_phone < 0) {
+		return EPARTY;
+	}
+
+	aid_t req =
+	    async_send_1(dma_srv_phone, DMA_SRV_UNREGISTER, id->id, &answer);
+	async_wait_for(req, &rc1);
+	return rc1;
+}
+
+/**
+ * Cleans all memory attached to client's id
+ * @param[in] id id of the device
+ * @return  according to dma_cli_cleanup
+ */
+int dma_cli_cleanup(dma_srv_dev_id_t * id)
+{
+	sysarg_t rc1;
+	ipc_call_t answer;
+	if (dma_srv_phone < 0) {
+		return EPARTY;
+	}
+	aid_t req = async_send_1(dma_srv_phone, DMA_SRV_CLEANUP, id->id, &answer);
+	async_wait_for(req, &rc1);
+	return rc1;
+}
+
+/**
+ * Locks memory at server.
+ * @param[in] area		pointer to begin of area
+ * @param[in] offset	offset in pages to DMA locked memory from begin of the area
+ * @param[in] pages		how many pages should be locked in memory
+ * @param[in] flags		flags of shared memory
+ * @param[in] id		id of the device
+ * @return  according to dma_srv_set_ownership
+ */
+int dma_cli_set_ownership(void * area, size_t offset, size_t pages,
+    unsigned int flags, dma_srv_dev_id_t * id)
+{
+	sysarg_t rc1;
+	ipc_call_t answer;
+	uspace_dma_print("Set ownership\n");
+	if (dma_srv_phone < 0) {
+		return EPARTY;
+	}
+	aid_t req = async_send_3(dma_srv_phone, DMA_SRV_SET_OWNERSHIP, id->id,
+	    offset, pages, &answer);
+	int rc2 = async_share_out_start(dma_srv_phone, area, flags);
+	async_wait_for(req, &rc1);
+	if (rc1 != EOK || rc2 != EOK) {
+		uspace_dma_print("rc1 %d, rc2 %d\n", (int) rc1, rc2);
+		return rc1;
+	}
+	return EOK;
+}
+
+/**
+ * Unlocks memory at server.
+ * @param[in] paddr	pointer to first physical frame of locked area
+ * @param[in] id	id of the device
+ * @return  according to dma_srv_clear_ownership
+ */
+int dma_cli_clear_ownership(void * paddr, dma_srv_dev_id_t * id)
+{
+	sysarg_t rc1;
+	ipc_call_t answer;
+	if (dma_srv_phone < 0) {
+		return EPARTY;
+	}
+	aid_t req = async_send_2(dma_srv_phone, DMA_SRV_CLEAR_OWNERSHIP, id->id,
+	    (sysarg_t) paddr, &answer);
+	async_wait_for(req, &rc1);
+	return rc1;
+
+}
+
+/**
+ * Initialization of DMA library
+ *
+ * @return on success EOK, otherwise proper errno value
+ */
+
+int dma_allocator_init(void)
+{
+	dma_srv_phone = service_connect_blocking(SERVICE_DMA, 0, 0);
+	if (dma_srv_phone < 0) {
+		return dma_srv_phone;
+	}
+	return EOK;
+}
+
+/**
+ * Unmaps and destroys DMA memory area.
+ * @param[in] virt_addr pointer to begin of the memory area.
+ *
+ * @return EOK on success or a value from @ref errno.h on failure.
+ */
+int dma_unmap(void * virt_addr)
+{
+	return as_area_destroy(virt_addr);
+}
+
+/**
+ * Highlevel interface of DMA allocator. Finds suitable virtual memory area to
+ * map physical memory.
+ *
+ * @param[in,out] mem_desc	Structure describing memory block to be allocated,
+ *							physmem and hadle parts will be filled
+ * @param[in] dma_flags		flags for type of allocated block
+ *
+ * @return on success EOK, otherwise proper errno value
+ */
+int dma_allocate_anonymous(dma_mem_t * mem_desc, int dma_flags)
+{
+	mem_desc->virtual = as_get_mappable_page(mem_desc->size * PAGE_SIZE);
+	return dma_allocate(&(mem_desc->physical), mem_desc->virtual,
+	    mem_desc->size, mem_desc->mapping_flags, dma_flags);
+
+}
+
+/**
+ * Unmaps and destroys DMA memory area.
+ * @param[in] mem pointer to memory area description.
+ *
+ * @return EOK on success or a value from @ref errno.h on failure.
+ */
+
+int dma_free(dma_mem_t * mem)
+{
+	return dma_unmap(mem->virtual);
+}
+
+
+
+/**
+ * Locks continguos memory area and fills to parameter it's physical address
+ * @param[in] vaddr		pointer to begin of virtual memory area
+ * @param[out] faddr	pointer to place where physical address of the continguos
+ * 						physical memory area should be filled
+ * @param[in] size_in	maximum size of locked area (in pages)
+ * @param[out] size_out	size of locked continguos area (in pages)
+ *
+ * @return	EOK on success (faddr and size_out are corrctly filled), otherwise
+ * 			proper error code according to code according to dma_lock_mem or
+ * 			copy_from_upsace copy_to_uspace
+ */
+
+int dma_lock(void * vaddr, void ** faddr, size_t size_in, size_t * size_out)
+{
+	(*size_out) = size_in;
+	return EOK;
+}
+
+
+/**
+ * Unlocks allready locked memory area and fills to parameter it's size
+ * @param[in] vaddr		pointer to begin of virtual memory area
+ * @param[in] size_in	maximum size of unlocked area
+ * @param[out] size_out	size of unlocked continguos area
+ *
+ * @return	EOK on success (faddr and size_out are corrctly filled), otherwise
+ * 			proper error code according to code according to dma_unlock_mem or
+ * 			copy_from_upsace copy_to_uspace
+ */
+
+int dma_unlock(void * vaddr, size_t size_in, size_t * size_out)
+{
+	
+	return EOK;
+}
+
+/** @}
+ */
+

=== added file 'uspace/lib/c/include/adt/avltree_generic.h'
--- uspace/lib/c/include/adt/avltree_generic.h	1970-01-01 00:00:00 +0000
+++ uspace/lib/c/include/adt/avltree_generic.h	2011-08-24 08:54:55 +0000
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2011 Radim Vansa, Jan Zaloha
+ * 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.
+ */
+
+/** @addtogroup genericadt
+ * @{
+ */
+
+/**
+ * @file
+ */
+#ifndef _AVLTREE_GENERIC_H_
+#define _AVLTREE_GENERIC_H_
+
+#ifdef KERNEL
+#include "print.h"
+typedef native_t avl_native_t;
+#else
+typedef int avl_native_t;
+#endif
+
+#define LEFT_TOO_LIGHT -2
+#define RIGHT_TOO_LIGHT 2
+#define LEFT_LIGHTER -1
+#define RIGHT_LIGHTER 1
+#define BALANCED 0
+
+#define SWAP(a, b) {a = (typeof(a))(((avl_native_t)(a))^((avl_native_t)(b)));\
+                    b = (typeof(a))(((avl_native_t)(a))^((avl_native_t)(b)));\
+                    a = (typeof(a))(((avl_native_t)(a))^((avl_native_t)(b)));}
+
+/**
+ * Node of AVL tree
+ * Contains pointer to left son, right son, parent and key
+ */
+typedef struct avltree_gen_node{
+        /**
+         * Data of the node
+         */
+	void *key;
+	/**
+	 * Left subtree of the node
+	 */
+	struct avltree_gen_node * left_son;
+	/**
+	 * Right subtree of the node
+	 */
+	struct avltree_gen_node * right_son;
+	/**
+	 * Parent of current node (NULL for root)
+	 */
+	struct avltree_gen_node * parent;
+	/**
+	 * Balance of subtrees in well balanced tree could be LEFT_LIGHTER, RIGHT_LIGHTER or BALANCED
+	 */
+	avl_native_t balance;
+} avltree_gen_node_t;
+
+extern void avltree_gen_node_init(avltree_gen_node_t * input_node, void *key);
+
+/**
+ * Wrapper of AVL tree
+ */
+typedef struct avltree_gen{
+        /**
+         * Function to compare nodes during adding or default saerching
+         */
+	int (*compare_keys)(void *, void*);
+	/**
+	 * Root of the tree.
+	 */
+	avltree_gen_node_t * root;
+} avltree_gen_t;
+
+extern void avltree_gen_init(avltree_gen_t * input_tree, int (*cmp)(void*, void*));
+extern void avltree_gen_insert(avltree_gen_t * input_tree, avltree_gen_node_t *node);
+extern avltree_gen_node_t * avltree_gen_find(avltree_gen_t * source, void * key);
+extern avltree_gen_node_t * avltree_gen_find_parametrized(avltree_gen_t * source, void * key, int (*cmp)(void*, void*));
+extern avltree_gen_node_t * avltree_gen_drop(avltree_gen_t * source, void * key);
+extern avltree_gen_node_t * avltree_gen_drop_parametrized(avltree_gen_t * source, void * key, int (*cmp)(void*, void*));
+extern void avltree_gen_traverse(const avltree_gen_node_t * a, unsigned int tabs);
+extern avltree_gen_node_t * avltree_gen_rem_node(avltree_gen_t * source, avltree_gen_node_t * node);
+extern void avltree_gen_print_parametrized(avltree_gen_t * source, void (*printer)(void*));
+extern avltree_gen_node_t * avltree_gen_get_min(avltree_gen_t * source);
+
+
+extern int avltree_gen_test(avltree_gen_node_t * input);
+extern int avltree_gen_test_cond(avltree_gen_t * input);
+
+#endif

=== added file 'uspace/lib/c/include/dma.h'
--- uspace/lib/c/include/dma.h	1970-01-01 00:00:00 +0000
+++ uspace/lib/c/include/dma.h	2011-08-30 20:40:10 +0000
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 2011 Jan Zaloha
+ * 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.
+ */
+/** @addtogroup dma_userspace
+ * @{
+ */
+
+/**
+ * @file
+ * @brief DMA related standard library functions
+ */
+
+#ifndef _DMA_H_
+#define _DMA_H_
+
+#include <sys/mman.h>
+#include <as.h>
+#include <stdio.h>
+
+#define DMA_24_BITS FRAME_DMA_24_BITS
+#define DMA_32_BITS FRAME_DMA_32_BITS
+
+#define DMA_SHARE 1
+//#define USPACE_DMA_DEBUG
+
+#ifdef USPACE_DMA_DEBUG
+#define uspace_dma_print(...)	printf(__VA_ARGS__)
+#else
+#define uspace_dma_print(...)
+#endif
+
+/**
+ * Structure describing block of dma allocated memory
+ */
+typedef struct dma_mem {
+	/**
+	 * Pointer to physical memory
+	 */
+	void * physical;
+	/**
+	 * Pointer to virtual memory
+	 */
+	void * virtual;
+	/**
+	 * Size in pages
+	 */
+	unsigned long size;
+	/**
+	 * Flags describing type of mapping
+	 */
+	int mapping_flags;
+} dma_mem_t;
+
+/**
+ * Unique identifier of DMA transfer
+ */
+typedef struct dma_transfer_id {
+	/**
+	 * ID of the transfer
+	 */
+	int id;
+} dma_transfer_id_t;
+
+#define DMA_TRANSFER_ID_TO_INT(x) 	(x).id
+#define DMA_TRANSFER_ID_INIT(x, y)	(x).id = y
+
+#define DMA_MAN_MAX_SPECIFIC 32
+/**
+ * Capabilities of DMA manager driver
+ */
+typedef struct dma_man_capabilities {
+	/**
+	 * Can destroy transfer
+	 */
+	bool destroy_transfer;
+	/**
+	 * Supports set_ procedures
+	 */
+	bool set_procedures;
+	/**
+	 * Supports get_ procedures
+	 */
+	bool add_procedures;
+	/**
+	 * Supports mem_ procedures
+	 */
+	bool mem_procedures;
+	/**
+	 * Device specific data
+	 */
+	int specific[DMA_MAN_MAX_SPECIFIC];
+} dma_man_capabilities_t;
+
+/**
+ * Status of a DMA transfer
+ */
+typedef struct dma_transfer_status {
+	/**
+	 * Bitfield describing status of the transfer
+	 */
+	int status;
+	/**
+	 * Size of completed part of transfer
+	 */
+	size_t size;
+} dma_transfer_status_t;
+
+/**
+ * Unknown transfer
+ */
+#define DMA_STATUS_UNKNOWN 	0x00000001
+/**
+ * Transfer is waiting to be ready
+ */
+#define DMA_STATUS_ENQUED	0x00000002
+/**
+ * Transfer is ready to begin, but not started
+ */
+#define DMA_STATUS_READY	0x00000004
+/**
+ * Transfer is in progress
+ */
+#define DMA_STATUS_PENDING	0x00000008
+/**
+ * Transfer has been finished
+ */
+#define DMA_STATUS_FINISHED	0x00000010
+/**
+ * Transfer has failed
+ */
+#define DMA_STATUS_FAILED	0x00000020
+
+#define DMA_TRANSFER_QUERY_UNKNOWN(x) 	((x).status & DMA_STATUS_UNKNOWN)
+#define DMA_TRANSFER_QUERY_ENQUED(x) 	((x).status & DMA_STATUS_ENQUED)
+#define DMA_TRANSFER_QUERY_READY(x)		((x).status & DMA_STATUS_READY)
+#define DMA_TRANSFER_QUERY_PENDING(x)	((x).status & DMA_STATUS_PENDING)
+#define DMA_TRANSFER_QUERY_FINISHED(x)	((x).status & DMA_STATUS_FINISHED)
+#define DMA_TRANSFER_QUERY_FAILED(x)	((x).status & DMA_STATUS_FAILED)
+
+#define DMA_TRANSFER_QUERY_COMPLETED_SIZE(x)	(x).size
+
+/**
+ * Structure describing channel of DMA transfer
+ */
+typedef struct dma_channel {
+	/**
+	 * ID of the channel
+	 */
+	int id;
+} dma_channel_t;
+
+/**
+ * Structure describing server registered instance
+ */
+typedef struct dma_srv_dev_id {
+	/**
+	 * Id of the instance
+	 */
+	uint64_t id;
+} dma_srv_dev_id_t;
+
+#define DMA_CHANNEL_TO_INT(x) 	(x).id
+#define DMA_CHANNEL_INIT(x, y) 	(x).id = y
+
+/**
+ * Structure describing flags of DMA transfer
+ */
+typedef struct dma_flags {
+	/**
+	 * ID of the channel
+	 */
+	int flags;
+} dma_flags_t;
+
+#define DMA_FLAGS_TO_INT(x)		(x).flags
+#define DMA_FLAGS_INIT(x, y)	(x).flags = y
+
+#define DMA_SRV_REGISTER 	100
+#define DMA_SRV_UNREGISTER	101
+#define DMA_SRV_CLEANUP		102
+#define DMA_SRV_SET_OWNERSHIP	103
+#define DMA_SRV_CLEAR_OWNERSHIP	104
+
+extern int dma_allocate(void **, void*, unsigned long, int, int);
+extern int dma_allocate_anonymous(dma_mem_t *, int);
+extern int dma_allocator_init(void);
+extern int dma_unmap(void *);
+extern int dma_free(dma_mem_t *);
+extern int dma_lock(void * vaddr, void ** faddr, size_t size_in,
+    size_t * size_out);
+extern int dma_unlock(void * vaddr, size_t size_in, size_t * size_out);
+extern int dma_cli_register(const char * client_identifier, dma_srv_dev_id_t *id);
+extern int dma_cli_unregister(dma_srv_dev_id_t * id);
+extern int dma_cli_cleanup(dma_srv_dev_id_t * id);
+extern int dma_cli_set_ownership(void * area, size_t offset, size_t number,
+    unsigned int flags, dma_srv_dev_id_t * id);
+extern int dma_cli_clear_ownership(void * paddr, dma_srv_dev_id_t* id);
+
+#endif
+
+/** @}
+ */

=== modified file 'uspace/lib/c/include/ipc/services.h'
--- uspace/lib/c/include/ipc/services.h	2011-03-23 17:15:15 +0000
+++ uspace/lib/c/include/ipc/services.h	2011-08-30 20:43:29 +0000
@@ -59,7 +59,8 @@
 	SERVICE_ICMP,
 	SERVICE_UDP,
 	SERVICE_TCP,
-	SERVICE_SOCKET
+	SERVICE_SOCKET,
+	SERVICE_DMA
 } services_t;
 
 #endif

=== added directory 'uspace/srv/dma_srv'
=== added file 'uspace/srv/dma_srv/Makefile'
--- uspace/srv/dma_srv/Makefile	1970-01-01 00:00:00 +0000
+++ uspace/srv/dma_srv/Makefile	2011-08-24 08:54:55 +0000
@@ -0,0 +1,9 @@
+
+USPACE_PREFIX = ../..
+BINARY = dma_srv
+STATIC_NEEDED = y
+
+SOURCES = \
+	dma_srv.c
+
+include $(USPACE_PREFIX)/Makefile.common
\ No newline at end of file

=== added file 'uspace/srv/dma_srv/dma_srv.c'
--- uspace/srv/dma_srv/dma_srv.c	1970-01-01 00:00:00 +0000
+++ uspace/srv/dma_srv/dma_srv.c	2011-08-30 21:09:16 +0000
@@ -0,0 +1,657 @@
+/*
+ * Copyright (c) 2011 Jan Zaloha
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <fibril_synch.h>
+#include <fibril.h>
+#include <errno.h>
+#include <dma.h>
+#include <async.h>
+#include <ipc/ns.h>
+#include <str.h>
+#include <ipc/services.h>
+#include <adt/avltree_generic.h>
+
+/** @addtogroup dma_userspace
+ * @{
+ */
+
+/**
+ * @file
+ * @brief DMA related standard library functions
+ */
+
+/**
+ * Strucutre describing the range of locked memory area
+ */
+typedef struct dma_srv_mem_area {
+	/**
+	 * Physical address of first frame
+	 */
+	void * paddr;
+	/**
+	 * Begin of reserved virtual memory area
+	 */
+	void * vaddr;
+	/**
+	 * Size in pages of the area
+	 */
+	size_t size;
+} dma_srv_mem_area_t;
+
+/**
+ * Strucuture containing tree of locked areas by one process
+ */
+typedef struct dma_client_tree {
+	/**
+	 * Tree of allready locked areas
+	 */
+	avltree_gen_t areas;
+	/**
+	 * Text identifier of the process
+	 */
+	char * name;
+	/**
+	 * Unique ID of session
+	 */
+	uint64_t id;
+} dma_client_tree_t;
+
+avltree_gen_t process_tree_name;
+avltree_gen_t process_tree_id;
+fibril_mutex_t process_lock;
+uint64_t id_gen;
+
+/**
+ * Compares two dma_srv_mem_area_t structures by physical address
+ * @param[in] a		pointer to left dma_srv_mem_area_t
+ * @param[in] b		pointer to right dma_srv_mem_area_t
+ * @return	LEFT_LIGHTER when left node has lower physical address
+ * 			RIGHT_LIGHTER when right node has lower physical address
+ *	 		BALANCED when both nodes has same physical address
+ */
+static int dma_srv_area_cmp(void * a, void * b)
+{
+	dma_srv_mem_area_t * l = (dma_srv_mem_area_t*) a;
+	dma_srv_mem_area_t * r = (dma_srv_mem_area_t*) b;
+	if (l->paddr < r->paddr) {
+		return LEFT_LIGHTER;
+	} else if (l->paddr > r->paddr) {
+		return RIGHT_LIGHTER;
+	} else {
+		return BALANCED;
+	}
+}
+
+/**
+ * Compares two dma_srv_client_t structures by string name
+ * @param[in] a		pointer to left dma_srv_client_t
+ * @param[in] b		pointer to right dma_srv_client_t
+ * @return	LEFT_LIGHTER when left node has lower name
+ * 		RIGHT_LIGHTER when right node has lower name
+ * 		BALANCED when both nodes has same name
+ */
+static int dma_srv_client_cmp_name(void * a, void * b)
+{
+	dma_client_tree_t * l = (dma_client_tree_t*) a;
+	dma_client_tree_t * r = (dma_client_tree_t*) b;
+
+	int ret = str_cmp(l->name, r->name);
+	if (ret == -1) {
+		return LEFT_LIGHTER;
+	}
+	if (ret == 1) {
+		return RIGHT_LIGHTER;
+	}
+	return BALANCED;
+}
+
+/**
+ * Compares two dma_srv_client_t structures by id
+ * @param[in] a		pointer to left dma_srv_client_t
+ * @param[in] b		pointer to right dma_srv_client_t
+ * @return	LEFT_LIGHTER when left node has lower id
+ * 		RIGHT_LIGHTER when right node has lower id
+ * 		BALANCED when both nodes has same id
+ */
+static int dma_srv_client_cmp_id(void * a, void * b)
+{
+	dma_client_tree_t * l = (dma_client_tree_t*) a;
+	dma_client_tree_t * r = (dma_client_tree_t*) b;
+
+	if (l->id < r->id) {
+		return LEFT_LIGHTER;
+	} else if (l->id > r->id) {
+		return RIGHT_LIGHTER;
+	}
+	return BALANCED;
+}
+
+/**
+ * Unlocks memory area represented by dma_srv_mem_area_t
+ * @param[in] area	Pointer to area which should be unlocked
+ *
+ * @return same as dma_unlock.
+ */
+static int dma_srv_unlock_area(dma_srv_mem_area_t * area)
+{
+	size_t count;
+	return dma_unlock(area->vaddr, area->size, &count);
+}
+
+/**
+ * Locks memory area represented by dma_srv_mem_area_t
+ * @param[in] area	Pointer to area which should be locked
+ *
+ * @return EOK.
+ */
+static int dma_srv_lock_area(dma_srv_mem_area_t * area, size_t offset,
+    size_t size)
+{
+	size_t count = size;
+	size_t currently_locked;
+	void * temp;
+	int * vaddr = (int*) (((void*) area->vaddr) + PAGE_SIZE * offset);
+	uspace_dma_print("dma_srv_lock_area\n");
+	if(dma_lock(vaddr, &(temp), count, &currently_locked) != EOK){
+		uspace_dma_print("error\n");
+		return EINVAL;
+	}
+	uspace_dma_print("Locked %d/%d, %p\n", (int) currently_locked, (int) count,
+	    vaddr);
+	area->paddr = temp;
+
+	count -= currently_locked;
+	vaddr = (void*)(((uintptr_t)vaddr) + currently_locked * PAGE_SIZE);
+	while (count > 0) {
+		dma_lock(vaddr, &temp, count, &currently_locked);
+		//uspace_dma_print("Locked %d/%d, %p\n", currently_locked, count, vaddr);
+		count -= currently_locked;
+		if (currently_locked == 0) {
+			return EINVAL;
+		}
+		vaddr = (void*)(((uintptr_t)vaddr) + currently_locked * PAGE_SIZE);
+	}
+	return EOK;
+
+}
+/**
+ * Inits main strucutures of the server.
+ */
+
+static void dma_srv_init()
+{
+	fibril_mutex_initialize(&process_lock);
+	avltree_gen_init(&process_tree_name, dma_srv_client_cmp_name);
+	avltree_gen_init(&process_tree_id, dma_srv_client_cmp_id);
+	id_gen = 444;
+}
+
+/**
+ * Creates all data structures needed for communication with client side
+ * @param[in] rid	id of invocation call
+ * @param[in] call	pointer to call parameters
+ *
+ * @return EOK on success, ENOMEM on low memory, otherwise same as
+ * 	async_data_write_receive
+ */
+static int dma_srv_register(ipc_callid_t rid, ipc_call_t *call)
+{
+	uspace_dma_print("DMA server register\n");
+	dma_client_tree_t * new_client = NULL;
+	avltree_gen_node_t * node_name = NULL;
+	avltree_gen_node_t * node_id = NULL;
+	avltree_gen_node_t * temp;
+	size_t length;
+	ipc_callid_t callid;
+	uint64_t id;
+	int rc = ENOMEM;
+
+	if ((new_client = malloc(sizeof(dma_client_tree_t))) == NULL) {
+		goto err;
+	}
+	if ((node_name = malloc(sizeof(avltree_gen_node_t))) == NULL) {
+		goto err;
+	}
+	if ((node_id = malloc(sizeof(avltree_gen_node_t))) == NULL) {
+		goto err;
+	}
+
+	avltree_gen_node_init(node_name, new_client);
+	avltree_gen_node_init(node_id, new_client);
+
+	if (!(rc = async_data_write_receive(&callid, &length))) {
+		async_answer_0(callid, rc);
+		goto err;
+	}
+	uspace_dma_print("DMA server register: buffer len: %d\n", (int)length);
+	if ((new_client->name = malloc((length + 1) * sizeof(char))) == NULL) {
+		rc = ENOMEM;
+		async_answer_0(callid, rc);
+		goto err;
+	}
+
+	if ((rc = async_data_write_finalize(callid, new_client->name, length))) {
+		uspace_dma_print("DMA server register failed: error %d\n", rc);
+		async_answer_0(callid, rc);
+		goto err;
+	}
+	uspace_dma_print("DMA server register: name %s\n", new_client->name);
+	uspace_dma_print("Data = %p\n", new_client);
+	fibril_mutex_lock(&process_lock);
+	if ((temp = avltree_gen_find(&process_tree_name, new_client)) == NULL) {
+		new_client->id = id_gen;
+		avltree_gen_init(&(new_client->areas), dma_srv_area_cmp);
+		id = id_gen;
+		++id_gen;
+		avltree_gen_insert(&process_tree_name, node_name);
+		avltree_gen_insert(&process_tree_id, node_id);
+	} else {
+		id = ((dma_client_tree_t*) (temp->key))->id;
+		free(new_client->name);
+		free(new_client);
+		free(node_name);
+		free(node_id);
+	}
+	fibril_mutex_unlock(&process_lock);
+
+	async_answer_0(callid, EOK);
+	async_answer_1(rid, EOK, id);
+
+	return EOK;
+	err: async_answer_1(rid, rc, 0);
+	if (new_client != NULL && new_client->name != NULL) {
+		free(new_client->name);
+	}
+	if (new_client != NULL) {
+		free(new_client);
+	}
+	if (node_name != NULL) {
+		free(node_name);
+	}
+	if (node_id != NULL) {
+		free(node_id);
+	}
+	return rc;
+}
+
+/**
+ * Destroys all data structures needed for communication with client side
+ * @param[in] rid	id of invocation call
+ * @param[in] call	pointer to call parameters
+ *
+ * @return EOK on success, ENOTSUP when locked area for the client still exists,
+ *	EINVAL when client id does not exist
+ */
+static int dma_srv_unregister(ipc_callid_t callid, ipc_call_t *call)
+{
+	dma_client_tree_t node;
+	node.id = IPC_GET_ARG1(*call);
+	fibril_mutex_lock(&process_lock);
+
+	avltree_gen_node_t * n = avltree_gen_find(&process_tree_id, &node);
+	dma_client_tree_t * real_node = (dma_client_tree_t*) n->key;
+
+	if (real_node == NULL) {
+		fibril_mutex_unlock(&process_lock);
+		async_answer_0(callid, EINVAL);
+		return EINVAL;
+	}
+
+	if ((avltree_gen_get_min(&(real_node->areas))) != NULL) {
+		fibril_mutex_unlock(&process_lock);
+		async_answer_0(callid, ENOTSUP);
+		return ENOTSUP;
+	}
+
+	avltree_gen_node_t * m = avltree_gen_find(&process_tree_name, real_node);
+	avltree_gen_rem_node(&process_tree_name, m);
+	avltree_gen_rem_node(&process_tree_id, n);
+	fibril_mutex_unlock(&process_lock);
+
+	free(real_node->name);
+	free(real_node);
+	free(m);
+	free(n);
+	async_answer_0(callid, EOK);
+	return EOK;
+}
+
+/**
+ * Destroys all areas locked by the client
+ * @param[in] rid	id of invocation call
+ * @param[in] call	pointer to call parameters
+ *
+ * @return EOK on success, EINVAL when client id does not exist
+ */
+static int dma_srv_cleanup(ipc_callid_t callid, ipc_call_t *call)
+{
+	dma_client_tree_t n;
+	n.id = IPC_GET_ARG1(*call);
+	fibril_mutex_lock(&process_lock);
+	uspace_dma_print("Cleanup\n");
+	avltree_gen_node_t * node = avltree_gen_find(&process_tree_id, &n);
+	if (node == NULL) {
+		fibril_mutex_unlock(&process_lock);
+		async_answer_0(callid, EINVAL);
+		return EINVAL;
+	}
+
+	dma_client_tree_t * tree = (dma_client_tree_t*) node->key;
+
+	while ((node = avltree_gen_get_min(&(tree->areas))) != NULL) {
+		uspace_dma_print("Unlock %p\n", node->key);
+		avltree_gen_rem_node(&(tree->areas), node);
+		dma_srv_unlock_area((dma_srv_mem_area_t*) node->key);
+		as_area_destroy(((dma_srv_mem_area_t*) node->key)->vaddr);
+		uspace_dma_print("free 1\n");
+		free(node->key);
+		uspace_dma_print("free 2\n");
+		free(node);
+	}
+
+	fibril_mutex_unlock(&process_lock);
+
+	async_answer_0(callid, EOK);
+	return EOK;
+}
+
+/**
+ * Destroys one locked area owned by client
+ * @param[in] rid	id of invocation call
+ * @param[in] call	pointer to call parameters
+ *
+ * @return EOK on success, EINVAL when client id or area does not exist
+ */
+static int dma_srv_clear_ownership(ipc_callid_t callid, ipc_call_t *call)
+{
+
+	dma_client_tree_t d;
+	d.id = IPC_GET_ARG1(*call);
+	dma_srv_mem_area_t area;
+	area.paddr = (void*) IPC_GET_ARG2(*call);
+
+	fibril_mutex_lock(&process_lock);
+	avltree_gen_node_t * node = avltree_gen_find(&process_tree_id, &d);
+
+	uspace_dma_print("Srv clear\n");
+	if (node == NULL) {
+		fibril_mutex_unlock(&process_lock);
+		async_answer_0(callid, EINVAL);
+		return EINVAL;
+	}
+
+	uspace_dma_print("Srv clear stage 1\n");
+	dma_client_tree_t * cli_tree = (dma_client_tree_t*) node->key;
+	uspace_dma_print("Srv clear stage 1.5 %p\n", cli_tree);
+	node = avltree_gen_find(&(cli_tree->areas), &area);
+
+	if (node == NULL) {
+		fibril_mutex_unlock(&process_lock);
+		async_answer_0(callid, EINVAL);
+		return EINVAL;
+	}
+
+	uspace_dma_print("Srv clear stage 2\n");
+	avltree_gen_rem_node(&(cli_tree->areas), node);
+	fibril_mutex_unlock(&process_lock);
+	uspace_dma_print("Srv clear stage 3\n");
+
+	dma_srv_unlock_area((dma_srv_mem_area_t*) node->key);
+	as_area_destroy(((dma_srv_mem_area_t*) node->key)->vaddr);
+	free(node->key);
+	free(node);
+	async_answer_0(callid, EOK);
+	return EOK;
+}
+
+/**
+ * Creates one locked area owned by client
+ * @param[in] rid	id of invocation call
+ * @param[in] call	pointer to call parameters
+ *
+ * @return EOK on success, EINVAL when client passes bad data,
+ *	ENOMEM on low memory
+ */
+static int dma_srv_set_ownership(ipc_callid_t rid, ipc_call_t *call)
+{
+	avltree_gen_node_t * node = NULL;
+	dma_srv_mem_area_t * area = NULL;
+	int rc = EINVAL;
+	ipc_callid_t callid;
+	size_t size;
+	unsigned flags;
+
+	uspace_dma_print("ownership\n");
+	node = malloc(sizeof(avltree_gen_node_t));
+	area = malloc(sizeof(dma_srv_mem_area_t));
+	if (node == NULL || area == NULL) {
+		rc = ENOMEM;
+		async_answer_0(rid, rc);
+		goto err;
+	}
+
+	dma_client_tree_t searched_node;
+	avltree_gen_node_t * n;
+	searched_node.id = IPC_GET_ARG1(*call);
+	size_t offset = IPC_GET_ARG2(*call);
+	size_t declared_size = IPC_GET_ARG3(*call);
+
+	fibril_mutex_lock(&process_lock);
+	uspace_dma_print("ownership from id %d\n", (int) searched_node.id);
+
+	if ((n = avltree_gen_find(&process_tree_id, &searched_node)) == NULL) {
+		async_answer_0(rid, rc);
+		fibril_mutex_unlock(&process_lock);
+		goto err;
+	}
+
+	uspace_dma_print("ownership from id %d stage 2\n", (int) searched_node.id);
+	fibril_mutex_unlock(&process_lock);
+
+	if (!(rc = async_share_out_receive(&callid, &size, &flags))) {
+		rc = EINVAL;
+		uspace_dma_print("ownership from id %d failed code %d\n",
+		    (int) searched_node.id, rc);
+		async_answer_0(callid, rc);
+		async_answer_0(rid, rc);
+		goto err;
+	}
+
+	if (size / PAGE_SIZE < offset + declared_size) {
+		rc = EINVAL;
+		uspace_dma_print("ownership from id %d failed code %d\n",
+		    (int) searched_node.id, rc);
+		async_answer_0(callid, rc);
+		async_answer_0(rid, rc);
+		goto err;
+	}
+
+	uspace_dma_print("ownership from id %d stage 3\n", (int) searched_node.id);
+
+	if (size % PAGE_SIZE || size == 0) {
+		rc = EINVAL;
+		uspace_dma_print("ownership from id %d failed\n",
+		    (int) searched_node.id);
+		async_answer_0(callid, rc);
+		async_answer_0(rid, rc);
+		goto err;
+	}
+
+	area->vaddr = as_get_mappable_page(size);
+
+	if (area->vaddr == NULL) {
+		rc = ENOMEM;
+		uspace_dma_print("ownership from id %d failed enomem\n",
+		    (int) searched_node.id);
+		async_answer_0(callid, rc);
+		async_answer_0(rid, rc);
+		goto err;
+
+	}
+
+	uspace_dma_print("ownership from id %d stage 3,5\n", (int) searched_node.id);
+	async_share_out_finalize(callid, (area->vaddr));
+	uspace_dma_print("ownership from id %d stage 4, %p\n",
+	    (int) searched_node.id, area->vaddr);
+	area->size = size / PAGE_SIZE;
+	uspace_dma_print("offset %d, size %d", (int)offset, (int)declared_size);
+	if ((rc = dma_srv_lock_area(area, offset, declared_size)) != EOK) {
+		async_answer_0(rid, rc);
+		as_area_destroy(area->vaddr);
+		goto err;
+	}
+
+	avltree_gen_node_init(node, area);
+	dma_client_tree_t * tree = (dma_client_tree_t*) n->key;
+
+	uspace_dma_print("ownership from id %d stage 5\n", (int) searched_node.id);
+
+	fibril_mutex_lock(&process_lock);
+	if (avltree_gen_find(&(tree->areas), node) != NULL) {
+		dma_srv_unlock_area(area);
+		as_area_destroy(area->vaddr);
+		rc = EINVAL;
+		goto err;
+	}
+	avltree_gen_insert(&(tree->areas), node);
+	fibril_mutex_unlock(&process_lock);
+
+	async_answer_0(rid, EOK);
+	uspace_dma_print("ownership from id %d finished\n", (int) searched_node.id);
+	return EOK;
+
+	err: if (node != NULL) {
+		free(node);
+	}
+	if (area != NULL) {
+		free(area);
+	}
+	return rc;
+}
+
+/** Process the module message.
+ *
+ * Distribute the message to the right module.
+ *
+ * @param[in]  callid       The message identifier.
+ * @param[in]  call         The message parameters.
+ *
+ * @return EOK on success.
+ * @return ENOTSUP if the message is not known.
+ * @return Other error codes.
+ *
+ */
+static int dma_proc_message(ipc_callid_t callid, ipc_call_t *call)
+{
+	int rc = ENOTSUP;
+	switch (IPC_GET_IMETHOD(*call)) {
+	case DMA_SRV_REGISTER:
+		rc = dma_srv_register(callid, call);
+		break;
+	case DMA_SRV_UNREGISTER:
+		rc = dma_srv_unregister(callid, call);
+		break;
+	case DMA_SRV_CLEANUP:
+		rc = dma_srv_cleanup(callid, call);
+		break;
+	case DMA_SRV_SET_OWNERSHIP:
+		rc = dma_srv_set_ownership(callid, call);
+		break;
+	case DMA_SRV_CLEAR_OWNERSHIP:
+		rc = dma_srv_clear_ownership(callid, call);
+		break;
+	default:
+		break;
+	}
+	return rc;
+}
+
+/** Default thread for new connections.
+ *
+ * @param[in] iid The initial message identifier.
+ * @param[in] icall The initial message call structure.
+ *
+ */
+
+static void dma_client_connection(ipc_callid_t iid, ipc_call_t *icall)
+{
+	async_answer_0(iid, EOK);
+
+	while (true) {
+		ipc_call_t call;
+		uspace_dma_print("Waiting for call\n");
+		ipc_callid_t callid = async_get_call(&call);
+
+		int rc = dma_proc_message(callid, &call);
+
+		if ((IPC_GET_IMETHOD(call) == IPC_M_PHONE_HUNGUP) || (rc == EHANGUP))
+			return;
+	}
+}
+
+/**
+ * Starts the DMA memory server
+ * @param[in] client_connetion	procedure processes IPC requests
+ *
+ * @return according to client_connection return code
+ */
+
+static int dma_srv_module_start(async_client_conn_t client_connection)
+{
+	int rc;
+
+	dma_srv_init();
+	async_set_client_connection(client_connection);
+
+	rc = async_connect_to_me(PHONE_NS, SERVICE_DMA, 0, 0, NULL);
+	if (rc != EOK) {
+		printf("asdf\n");
+		goto error;
+	}
+
+	async_manager();
+
+	error: return rc;
+}
+
+int main(int argc, char * argv[])
+{
+	int rc;
+
+	rc = dma_srv_module_start(dma_client_connection);
+	if (rc != EOK) {	
+		return rc;
+	}
+
+	return EOK;
+
+}
+/** @}
+ */