Index: Makefile
===================================================================
--- Makefile	(revision 6e5dc07f868b16c838c79bc42117b6116010e91b)
+++ Makefile	(revision f568ee7ca6382a57f76ee8c0cb5ff31f8955baf1)
@@ -28,4 +28,5 @@
 
 CSCOPE = cscope
+CHECK = tools/check.sh
 CONFIG = tools/config.py
 AUTOTOOL = tools/autotool.py
@@ -41,5 +42,5 @@
 CONFIG_HEADER = config.h
 
-.PHONY: all precheck cscope autotool config_auto config_default config distclean clean
+.PHONY: all precheck cscope autotool config_auto config_default config distclean clean check
 
 all: $(COMMON_MAKEFILE) $(COMMON_HEADER) $(CONFIG_MAKEFILE) $(CONFIG_HEADER)
@@ -54,4 +55,12 @@
 cscope:
 	find kernel boot uspace -regex '^.*\.[chsS]$$' | xargs $(CSCOPE) -b -k -u -f$(CSCOPE).out
+
+# Pre-integration build check
+check: $(CHECK)
+ifdef JOBS 
+	$(CHECK) -j $(JOBS)
+else
+	$(CHECK)
+endif
 
 $(COMMON_MAKEFILE): autotool
Index: tools/check.sh
===================================================================
--- tools/check.sh	(revision f568ee7ca6382a57f76ee8c0cb5ff31f8955baf1)
+++ tools/check.sh	(revision f568ee7ca6382a57f76ee8c0cb5ff31f8955baf1)
@@ -0,0 +1,89 @@
+#! /bin/bash
+
+#
+# Copyright (c) 2010 Jakub Jermar 
+# 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.
+#
+
+if [ $1" " == "-h " ];
+then
+	echo "Perform pre-integration hands-off build of all profiles."
+	echo
+	echo "Syntax:"
+	echo " $0 [-h] [args...]"
+	echo
+	echo " -h        Print this help."
+	echo " args...   All other args are passed to make (e.g. -j 6)"
+	echo
+
+	exit
+fi
+
+FAILED=""
+PASSED=""
+PROFILES=""
+DIRS=`find defaults/ -name Makefile.config | sed 's/^defaults\/\(.*\)\/Makefile.config/\1/' | sort`
+
+for D in $DIRS;
+do
+	for H in $DIRS;
+	do
+		if [ `echo $H | grep "^$D\/.*"`x != "x"  ];
+		then
+			continue 2 
+		fi
+	done
+	PROFILES="$PROFILES $D"
+done
+
+echo ">>> Going to build the following profiles:"
+echo $PROFILES
+
+for P in $PROFILES;
+do
+	echo -n ">>>> Building $P... "
+	( make distclean && make PROFILE=$P HANDS_OFF=y $1 ) >>/dev/null 2>>/dev/null
+	if [ $? -ne 0 ];
+	then
+		FAILED="$FAILED $P"
+		echo "failed."
+	else
+		PASSED="$PASSED $P"
+		echo "ok."
+	fi
+done
+
+echo ">>> Done."
+echo
+
+echo ">>> The following profiles passed:"
+echo $PASSED
+echo
+
+echo ">>> The following profiles failed:"
+echo $FAILED
+echo
+
Index: uspace/app/tester/Makefile
===================================================================
--- uspace/app/tester/Makefile	(revision 6e5dc07f868b16c838c79bc42117b6116010e91b)
+++ uspace/app/tester/Makefile	(revision f568ee7ca6382a57f76ee8c0cb5ff31f8955baf1)
@@ -55,4 +55,5 @@
 	loop/loop1.c \
 	mm/malloc1.c \
+	hw/misc/virtchar1.c \
 	hw/serial/serial1.c
 
Index: uspace/app/tester/hw/misc/virtchar1.c
===================================================================
--- uspace/app/tester/hw/misc/virtchar1.c	(revision f568ee7ca6382a57f76ee8c0cb5ff31f8955baf1)
+++ uspace/app/tester/hw/misc/virtchar1.c	(revision f568ee7ca6382a57f76ee8c0cb5ff31f8955baf1)
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2010 Vojtech Horky
+ * 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 tester
+ * @brief Test the virtual char driver
+ * @{
+ */
+/**
+ * @file
+ */
+
+#include <inttypes.h>
+#include <errno.h>
+#include <str_error.h>
+#include <sys/types.h>
+#include <async.h>
+#include <device/char.h>
+#include <str.h>
+#include <vfs/vfs.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <device/char.h>
+#include "../../tester.h"
+
+#define DEVICE_PATH_NORMAL "/dev/devices/\\virt\\null"
+#define DEVICE_PATH_CLASSES "/dev/class/virt-null\\1"
+#define BUFFER_SIZE 64
+
+static const char *test_virtchar1_internal(const char *path)
+{
+	TPRINTF("Opening `%s'...\n", path);
+	int fd = open(path, O_RDONLY);
+	if (fd < 0) {
+		TPRINTF("   ...error: %s\n", str_error(fd));
+		if (fd == ENOENT) {
+			TPRINTF("   (error was ENOENT: " \
+			    "have you compiled test drivers?)\n");
+		}
+		return "Failed opening devman driver device for reading";
+	}
+	
+	TPRINTF("   ...file handle %d\n", fd);
+
+	TPRINTF(" Asking for phone...\n");
+	int phone = fd_phone(fd);
+	if (phone < 0) {
+		close(fd);
+		TPRINTF("   ...error: %s\n", str_error(phone));
+		return "Failed to get phone to device";
+	}
+	TPRINTF("   ...phone is %d\n", phone);
+	
+	TPRINTF(" Will try to read...\n");
+	size_t i;
+	char buffer[BUFFER_SIZE];
+	read_dev(phone, buffer, BUFFER_SIZE);
+	TPRINTF(" ...verifying that we read zeroes only...\n");
+	for (i = 0; i < BUFFER_SIZE; i++) {
+		if (buffer[i] != 0) {
+			return "Not all bytes are zeroes";
+		}
+	}
+	TPRINTF("   ...data read okay\n");
+	
+	/* Clean-up. */
+	TPRINTF(" Closing phones and file descriptors\n");
+	ipc_hangup(phone);
+	close(fd);
+	
+	return NULL;
+}
+
+const char *test_virtchar1(void)
+{;
+	const char *res;
+
+	res = test_virtchar1_internal(DEVICE_PATH_NORMAL);
+	if (res != NULL) {
+		return res;
+	}
+
+	res = test_virtchar1_internal(DEVICE_PATH_CLASSES);
+	if (res != NULL) {
+		return res;
+	}
+
+	return NULL;
+}
+
+/** @}
+ */
Index: uspace/app/tester/hw/misc/virtchar1.def
===================================================================
--- uspace/app/tester/hw/misc/virtchar1.def	(revision f568ee7ca6382a57f76ee8c0cb5ff31f8955baf1)
+++ uspace/app/tester/hw/misc/virtchar1.def	(revision f568ee7ca6382a57f76ee8c0cb5ff31f8955baf1)
@@ -0,0 +1,6 @@
+{
+	"virtchar1",
+	"Virtual char device test",
+	&test_virtchar1,
+	false
+},
Index: uspace/app/tester/tester.c
===================================================================
--- uspace/app/tester/tester.c	(revision 6e5dc07f868b16c838c79bc42117b6116010e91b)
+++ uspace/app/tester/tester.c	(revision f568ee7ca6382a57f76ee8c0cb5ff31f8955baf1)
@@ -66,4 +66,5 @@
 #include "hw/serial/serial1.def"
 #include "adt/usbaddrkeep.def"
+#include "hw/misc/virtchar1.def"
 	{NULL, NULL, NULL, false}
 };
Index: uspace/app/tester/tester.h
===================================================================
--- uspace/app/tester/tester.h	(revision 6e5dc07f868b16c838c79bc42117b6116010e91b)
+++ uspace/app/tester/tester.h	(revision f568ee7ca6382a57f76ee8c0cb5ff31f8955baf1)
@@ -83,4 +83,5 @@
 extern const char *test_serial1(void);
 extern const char *test_usbaddrkeep(void);
+extern const char *test_virtchar1(void);
 
 extern test_t tests[];
Index: uspace/drv/rootvirt/devices.def
===================================================================
--- uspace/drv/rootvirt/devices.def	(revision 6e5dc07f868b16c838c79bc42117b6116010e91b)
+++ uspace/drv/rootvirt/devices.def	(revision f568ee7ca6382a57f76ee8c0cb5ff31f8955baf1)
@@ -17,4 +17,8 @@
 	.match_id = "virtual&test2"
 },
+{
+	.name = "null",
+	.match_id = "virtual&test1"
+},
 #endif
 /* Virtual USB host controller. */
Index: uspace/drv/test1/Makefile
===================================================================
--- uspace/drv/test1/Makefile	(revision 6e5dc07f868b16c838c79bc42117b6116010e91b)
+++ uspace/drv/test1/Makefile	(revision f568ee7ca6382a57f76ee8c0cb5ff31f8955baf1)
@@ -33,4 +33,5 @@
 
 SOURCES = \
+	char.c \
 	test1.c
 
Index: uspace/drv/test1/char.c
===================================================================
--- uspace/drv/test1/char.c	(revision f568ee7ca6382a57f76ee8c0cb5ff31f8955baf1)
+++ uspace/drv/test1/char.c	(revision f568ee7ca6382a57f76ee8c0cb5ff31f8955baf1)
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2010 Vojtech Horky
+ * 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.
+ */
+
+/** @file
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <mem.h>
+#include <char.h>
+
+#include "test1.h"
+
+static int impl_char_read(device_t *dev, char *buf, size_t count) {
+	memset(buf, 0, count);
+	return count;
+}
+
+static int imp_char_write(device_t *dev, char *buf, size_t count) {
+	return count;
+}
+
+static char_iface_t char_interface = {
+	.read = &impl_char_read,
+	.write = &imp_char_write
+};
+
+device_ops_t char_device_ops = {
+	.interfaces[CHAR_DEV_IFACE] = &char_interface
+};
+
Index: uspace/drv/test1/test1.c
===================================================================
--- uspace/drv/test1/test1.c	(revision 6e5dc07f868b16c838c79bc42117b6116010e91b)
+++ uspace/drv/test1/test1.c	(revision f568ee7ca6382a57f76ee8c0cb5ff31f8955baf1)
@@ -34,7 +34,5 @@
 #include <errno.h>
 #include <str_error.h>
-#include <driver.h>
-
-#define NAME "test1"
+#include "test1.h"
 
 static int add_device(device_t *dev);
@@ -98,5 +96,8 @@
 	add_device_to_class(dev, "virtual");
 
-	if (dev->parent == NULL) {
+	if (str_cmp(dev->name, "null") == 0) {
+		dev->ops = &char_device_ops;
+		add_device_to_class(dev, "virt-null");
+	} else if (dev->parent == NULL) {
 		register_child_verbose(dev, "cloning myself ;-)", "clone",
 		    "virtual&test1", 10);
@@ -117,3 +118,2 @@
 }
 
-
Index: uspace/drv/test1/test1.h
===================================================================
--- uspace/drv/test1/test1.h	(revision f568ee7ca6382a57f76ee8c0cb5ff31f8955baf1)
+++ uspace/drv/test1/test1.h	(revision f568ee7ca6382a57f76ee8c0cb5ff31f8955baf1)
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2010 Vojtech Horky
+ * 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.
+ */
+
+/** @file
+ */
+#ifndef DRV_TEST1_TEST1_H_
+#define DRV_TEST1_TEST1_H_
+
+#include <driver.h>
+
+#define NAME "test1"
+
+extern device_ops_t char_device_ops;
+
+#endif
Index: uspace/lib/c/generic/devmap.c
===================================================================
--- uspace/lib/c/generic/devmap.c	(revision 6e5dc07f868b16c838c79bc42117b6116010e91b)
+++ uspace/lib/c/generic/devmap.c	(revision f568ee7ca6382a57f76ee8c0cb5ff31f8955baf1)
@@ -127,5 +127,54 @@
 /** Register new device.
  *
- * @param namespace Namespace name.
+ * The @p interface is used when forwarding connection to the driver.
+ * If not 0, the first argument is the interface and the second argument
+ * is the devmap handle of the device.
+ * When the interface is zero (default), the first argument is directly
+ * the handle (to ensure backward compatibility).
+ *
+ * @param fqdn Fully qualified device name.
+ * @param[out] handle Handle to the created instance of device.
+ * @param interface Interface when forwarding.
+ *
+ */
+int devmap_device_register_with_iface(const char *fqdn,
+    devmap_handle_t *handle, sysarg_t interface)
+{
+	int phone = devmap_get_phone(DEVMAP_DRIVER, IPC_FLAG_BLOCKING);
+	
+	if (phone < 0)
+		return phone;
+	
+	async_serialize_start();
+	
+	ipc_call_t answer;
+	aid_t req = async_send_2(phone, DEVMAP_DEVICE_REGISTER, interface, 0,
+	    &answer);
+	
+	sysarg_t retval = async_data_write_start(phone, fqdn, str_size(fqdn));
+	if (retval != EOK) {
+		async_wait_for(req, NULL);
+		async_serialize_end();
+		return retval;
+	}
+	
+	async_wait_for(req, &retval);
+	
+	async_serialize_end();
+	
+	if (retval != EOK) {
+		if (handle != NULL)
+			*handle = -1;
+		return retval;
+	}
+	
+	if (handle != NULL)
+		*handle = (devmap_handle_t) IPC_GET_ARG1(answer);
+	
+	return retval;
+}
+
+/** Register new device.
+ *
  * @param fqdn      Fully qualified device name.
  * @param handle    Output: Handle to the created instance of device.
@@ -134,37 +183,7 @@
 int devmap_device_register(const char *fqdn, devmap_handle_t *handle)
 {
-	int phone = devmap_get_phone(DEVMAP_DRIVER, IPC_FLAG_BLOCKING);
-	
-	if (phone < 0)
-		return phone;
-	
-	async_serialize_start();
-	
-	ipc_call_t answer;
-	aid_t req = async_send_2(phone, DEVMAP_DEVICE_REGISTER, 0, 0,
-	    &answer);
-	
-	sysarg_t retval = async_data_write_start(phone, fqdn, str_size(fqdn));
-	if (retval != EOK) {
-		async_wait_for(req, NULL);
-		async_serialize_end();
-		return retval;
-	}
-	
-	async_wait_for(req, &retval);
-	
-	async_serialize_end();
-	
-	if (retval != EOK) {
-		if (handle != NULL)
-			*handle = -1;
-		return retval;
-	}
-	
-	if (handle != NULL)
-		*handle = (devmap_handle_t) IPC_GET_ARG1(answer);
-	
-	return retval;
-}
+	return devmap_device_register_with_iface(fqdn, handle, 0);
+}
+
 
 int devmap_device_get_handle(const char *fqdn, devmap_handle_t *handle, unsigned int flags)
Index: uspace/lib/c/generic/net/modules.c
===================================================================
--- uspace/lib/c/generic/net/modules.c	(revision 6e5dc07f868b16c838c79bc42117b6116010e91b)
+++ uspace/lib/c/generic/net/modules.c	(revision f568ee7ca6382a57f76ee8c0cb5ff31f8955baf1)
@@ -198,44 +198,4 @@
 }
 
-/** Receives data from the other party.
- *
- * The received data buffer is allocated and returned.
- *
- * @param[out] data	The data buffer to be filled.
- * @param[out] length	The buffer length.
- * @return		EOK on success.
- * @return		EBADMEM if the data or the length parameter is NULL.
- * @return		EINVAL if the client does not send data.
- * @return		ENOMEM if there is not enough memory left.
- * @return		Other error codes as defined for the
- *			async_data_write_finalize() function.
- */
-int data_receive(void **data, size_t *length)
-{
-	ipc_callid_t callid;
-	int rc;
-
-	if (!data || !length)
-		return EBADMEM;
-
-	// fetch the request
-	if (!async_data_write_receive(&callid, length))
-		return EINVAL;
-
-	// allocate the buffer
-	*data = malloc(*length);
-	if (!*data)
-		return ENOMEM;
-
-	// fetch the data
-	rc = async_data_write_finalize(callid, *data, *length);
-	if (rc != EOK) {
-		free(data);
-		return rc;
-	}
-
-	return EOK;
-}
-
 /** Replies the data to the other party.
  *
Index: uspace/lib/c/include/devmap.h
===================================================================
--- uspace/lib/c/include/devmap.h	(revision 6e5dc07f868b16c838c79bc42117b6116010e91b)
+++ uspace/lib/c/include/devmap.h	(revision f568ee7ca6382a57f76ee8c0cb5ff31f8955baf1)
@@ -45,4 +45,5 @@
 extern int devmap_driver_register(const char *, async_client_conn_t);
 extern int devmap_device_register(const char *, devmap_handle_t *);
+extern int devmap_device_register_with_iface(const char *, devmap_handle_t *, sysarg_t);
 
 extern int devmap_device_get_handle(const char *, devmap_handle_t *, unsigned int);
Index: uspace/lib/c/include/ipc/devman.h
===================================================================
--- uspace/lib/c/include/ipc/devman.h	(revision 6e5dc07f868b16c838c79bc42117b6116010e91b)
+++ uspace/lib/c/include/ipc/devman.h	(revision f568ee7ca6382a57f76ee8c0cb5ff31f8955baf1)
@@ -123,4 +123,5 @@
 	DEVMAN_CLIENT,
 	DEVMAN_CONNECT_TO_DEVICE,
+	DEVMAN_CONNECT_FROM_DEVMAP,
 	DEVMAN_CONNECT_TO_PARENTS_DEVICE
 } devman_interface_t;
Index: uspace/lib/c/include/net/modules.h
===================================================================
--- uspace/lib/c/include/net/modules.h	(revision 6e5dc07f868b16c838c79bc42117b6116010e91b)
+++ uspace/lib/c/include/net/modules.h	(revision f568ee7ca6382a57f76ee8c0cb5ff31f8955baf1)
@@ -49,21 +49,4 @@
 #include <sys/time.h>
 
-/** Converts the data length between different types.
- *
- * @param[in] type_from	The source type.
- * @param[in] type_to	The destination type.
- * @param[in] count	The number units of the source type size.
- */
-#define CONVERT_SIZE(type_from, type_to, count) \
-	((sizeof(type_from) / sizeof(type_to)) * (count))
-
-/** Registers the module service at the name server.
- *
- * @param[in] me	The module service.
- * @param[out] phonehash The created phone hash.
- */
-#define REGISTER_ME(me, phonehash) \
-	ipc_connect_to_me(PHONE_NS, (me), 0, 0, (phonehash))
-
 /** Connect to the needed module function type definition.
  *
@@ -80,5 +63,4 @@
 extern int connect_to_service(services_t);
 extern int connect_to_service_timeout(services_t, suseconds_t);
-extern int data_receive(void **, size_t *);
 extern int data_reply(void *, size_t);
 extern void refresh_answer(ipc_call_t *, int *);
Index: uspace/srv/devman/devman.c
===================================================================
--- uspace/srv/devman/devman.c	(revision 6e5dc07f868b16c838c79bc42117b6116010e91b)
+++ uspace/srv/devman/devman.c	(revision f568ee7ca6382a57f76ee8c0cb5ff31f8955baf1)
@@ -62,4 +62,14 @@
 }
 
+static int devmap_devices_class_compare(unsigned long key[], hash_count_t keys,
+    link_t *item)
+{
+	dev_class_info_t *class_info
+	    = hash_table_get_instance(item, dev_class_info_t, devmap_link);
+	assert(class_info != NULL);
+
+	return (class_info->devmap_handle == (devmap_handle_t) key[0]);
+}
+
 static void devices_remove_callback(link_t *item)
 {
@@ -75,4 +85,10 @@
 	.hash = devices_hash,
 	.compare = devmap_devices_compare,
+	.remove_callback = devices_remove_callback
+};
+
+static hash_table_operations_t devmap_devices_class_ops = {
+	.hash = devices_hash,
+	.compare = devmap_devices_class_compare,
 	.remove_callback = devices_remove_callback
 };
@@ -678,5 +694,6 @@
 	}
 	
-	devmap_device_register(devmap_pathname, &node->devmap_handle);
+	devmap_device_register_with_iface(devmap_pathname,
+	    &node->devmap_handle, DEVMAN_CONNECT_FROM_DEVMAP);
 	
 	tree_add_devmap_device(tree, node);
@@ -1050,6 +1067,10 @@
 	
 	info = (dev_class_info_t *) malloc(sizeof(dev_class_info_t));
-	if (info != NULL)
+	if (info != NULL) {
 		memset(info, 0, sizeof(dev_class_info_t));
+		list_initialize(&info->dev_classes);
+		list_initialize(&info->devmap_link);
+		list_initialize(&info->link);
+	}
 	
 	return info;
@@ -1175,5 +1196,5 @@
 	fibril_rwlock_initialize(&class_list->rwlock);
 	hash_table_create(&class_list->devmap_devices, DEVICE_BUCKETS, 1,
-	    &devmap_devices_ops);
+	    &devmap_devices_class_ops);
 }
 
@@ -1223,4 +1244,6 @@
 	hash_table_insert(&class_list->devmap_devices, &key, &cli->devmap_link);
 	fibril_rwlock_write_unlock(&class_list->rwlock);
+
+	assert(find_devmap_class_device(class_list, cli->devmap_handle) != NULL);
 }
 
Index: uspace/srv/devman/main.c
===================================================================
--- uspace/srv/devman/main.c	(revision 6e5dc07f868b16c838c79bc42117b6116010e91b)
+++ uspace/srv/devman/main.c	(revision f568ee7ca6382a57f76ee8c0cb5ff31f8955baf1)
@@ -281,5 +281,6 @@
 	 * handle.
 	 */
-	devmap_device_register(devmap_pathname, &cli->devmap_handle);
+	devmap_device_register_with_iface(devmap_pathname,
+	    &cli->devmap_handle, DEVMAN_CONNECT_FROM_DEVMAP);
 	
 	/*
@@ -486,5 +487,5 @@
 static void devman_connection_devmapper(ipc_callid_t iid, ipc_call_t *icall)
 {
-	devmap_handle_t devmap_handle = IPC_GET_IMETHOD(*icall);
+	devmap_handle_t devmap_handle = IPC_GET_ARG2(*icall);
 	node_t *dev;
 
@@ -503,8 +504,8 @@
 	}
 	
-	printf(NAME ": devman_connection_devmapper: forward connection to "
-	    "device %s to driver %s.\n", dev->pathname, dev->drv->name);
 	ipc_forward_fast(iid, dev->drv->phone, DRIVER_CLIENT, dev->handle, 0,
 	    IPC_FF_NONE);
+	printf(NAME ": devman_connection_devmapper: forwarded connection to "
+	    "device %s to driver %s.\n", dev->pathname, dev->drv->name);
 }
 
@@ -512,22 +513,4 @@
 static void devman_connection(ipc_callid_t iid, ipc_call_t *icall)
 {
-	/*
-	 * Silly hack to enable the device manager to register as a driver by
-	 * the device mapper. If the ipc method is not IPC_M_CONNECT_ME_TO, this
-	 * is not the forwarded connection from naming service, so it must be a
-	 * connection from the devmapper which thinks this is a devmapper-style
-	 * driver. So pretend this is a devmapper-style driver. (This does not
-	 * work for device with handle == IPC_M_CONNECT_ME_TO, because devmapper
-	 * passes device handle to the driver as an ipc method.)
-	 */
-	if (IPC_GET_IMETHOD(*icall) != IPC_M_CONNECT_ME_TO)
-		devman_connection_devmapper(iid, icall);
-
-	/*
-	 * ipc method is IPC_M_CONNECT_ME_TO, so this is forwarded connection
-	 * from naming service by which we registered as device manager, so be
-	 * device manager.
-	 */
-	
 	/* Select interface. */
 	switch ((sysarg_t) (IPC_GET_ARG1(*icall))) {
@@ -542,4 +525,8 @@
 		devman_forward(iid, icall, false);
 		break;
+	case DEVMAN_CONNECT_FROM_DEVMAP:
+		/* Someone connected through devmap node. */
+		devman_connection_devmapper(iid, icall);
+		break;
 	case DEVMAN_CONNECT_TO_PARENTS_DEVICE:
 		/* Connect client to selected device. */
Index: uspace/srv/devmap/devmap.c
===================================================================
--- uspace/srv/devmap/devmap.c	(revision 6e5dc07f868b16c838c79bc42117b6116010e91b)
+++ uspace/srv/devmap/devmap.c	(revision f568ee7ca6382a57f76ee8c0cb5ff31f8955baf1)
@@ -99,4 +99,6 @@
 	/** Device driver handling this device */
 	devmap_driver_t *driver;
+	/** Use this interface when forwarding to driver. */
+	sysarg_t forward_interface;
 } devmap_device_t;
 
@@ -517,4 +519,7 @@
 	}
 	
+	/* Set the interface, if any. */
+	device->forward_interface = IPC_GET_ARG1(*icall);
+
 	/* Get fqdn */
 	char *fqdn;
@@ -566,5 +571,5 @@
 	/* Get unique device handle */
 	device->handle = devmap_create_handle();
-	
+
 	devmap_namespace_addref(namespace, device);
 	device->driver = driver;
@@ -617,6 +622,13 @@
 	}
 	
-	ipc_forward_fast(callid, dev->driver->phone, dev->handle,
-	    IPC_GET_ARG3(*call), 0, IPC_FF_NONE);
+	if (dev->forward_interface == 0) {
+		ipc_forward_fast(callid, dev->driver->phone,
+		    dev->handle, 0, 0,
+		    IPC_FF_NONE);
+	} else {
+		ipc_forward_fast(callid, dev->driver->phone,
+		    dev->forward_interface, dev->handle, 0,
+		    IPC_FF_NONE);
+	}
 	
 	fibril_mutex_unlock(&devices_list_mutex);
Index: uspace/srv/hw/netif/dp8390/dp8390_module.c
===================================================================
--- uspace/srv/hw/netif/dp8390/dp8390_module.c	(revision 6e5dc07f868b16c838c79bc42117b6116010e91b)
+++ uspace/srv/hw/netif/dp8390/dp8390_module.c	(revision f568ee7ca6382a57f76ee8c0cb5ff31f8955baf1)
@@ -197,5 +197,5 @@
 		return rc;
 	address->value = (char *) (&((dpeth_t *) device->specific)->de_address);
-	address->length = CONVERT_SIZE(ether_addr_t, char, 1);
+	address->length = sizeof(ether_addr_t);
 	return EOK;
 }
@@ -310,5 +310,5 @@
 	async_set_interrupt_received(irq_handler);
 
-	return REGISTER_ME(SERVICE_DP8390, &phonehash);
+	return ipc_connect_to_me(PHONE_NS, SERVICE_DP8390, 0, 0, &phonehash);
 }
 
Index: uspace/srv/net/il/arp/arp.c
===================================================================
--- uspace/srv/net/il/arp/arp.c	(revision 6e5dc07f868b16c838c79bc42117b6116010e91b)
+++ uspace/srv/net/il/arp/arp.c	(revision f568ee7ca6382a57f76ee8c0cb5ff31f8955baf1)
@@ -483,18 +483,14 @@
 	des_proto = des_hw + header->hardware_length;
 	trans = arp_addr_find(&proto->addresses, (char *) src_proto,
-	    CONVERT_SIZE(uint8_t, char, header->protocol_length));
+	    header->protocol_length);
 	/* Exists? */
 	if (trans && trans->hw_addr) {
-		if (trans->hw_addr->length != CONVERT_SIZE(uint8_t, char,
-		    header->hardware_length)) {
+		if (trans->hw_addr->length != header->hardware_length)
 			return EINVAL;
-		}
 		memcpy(trans->hw_addr->value, src_hw, trans->hw_addr->length);
 	}
 	/* Is my protocol address? */
-	if (proto->addr->length != CONVERT_SIZE(uint8_t, char,
-	    header->protocol_length)) {
+	if (proto->addr->length != header->protocol_length)
 		return EINVAL;
-	}
 	if (!str_lcmp(proto->addr->value, (char *) des_proto,
 	    proto->addr->length)) {
@@ -507,6 +503,5 @@
 			fibril_condvar_initialize(&trans->cv);
 			rc = arp_addr_add(&proto->addresses, (char *) src_proto,
-			    CONVERT_SIZE(uint8_t, char, header->protocol_length),
-			    trans);
+			    header->protocol_length, trans);
 			if (rc != EOK) {
 				/* The generic char map has already freed trans! */
@@ -516,6 +511,5 @@
 		if (!trans->hw_addr) {
 			trans->hw_addr = measured_string_create_bulk(
-			    (char *) src_hw, CONVERT_SIZE(uint8_t, char,
-			    header->hardware_length));
+			    (char *) src_hw, header->hardware_length);
 			if (!trans->hw_addr)
 				return ENOMEM;
@@ -606,6 +600,5 @@
 
 	/* ARP packet content size = header + (address + translation) * 2 */
-	length = 8 + 2 * (CONVERT_SIZE(char, uint8_t, proto->addr->length) +
-	    CONVERT_SIZE(char, uint8_t, device->addr->length));
+	length = 8 + 2 * (proto->addr->length + device->addr->length);
 	if (length > device->packet_dimension.content)
 		return ELIMIT;
@@ -640,6 +633,5 @@
 
 	rc = packet_set_addr(packet, (uint8_t *) device->addr->value,
-	    (uint8_t *) device->broadcast_addr->value,
-	    CONVERT_SIZE(char, uint8_t, device->addr->length));
+	    (uint8_t *) device->broadcast_addr->value, device->addr->length);
 	if (rc != EOK) {
 		pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
Index: uspace/srv/net/il/arp/arp_module.c
===================================================================
--- uspace/srv/net/il/arp/arp_module.c	(revision 6e5dc07f868b16c838c79bc42117b6116010e91b)
+++ uspace/srv/net/il/arp/arp_module.c	(revision f568ee7ca6382a57f76ee8c0cb5ff31f8955baf1)
@@ -79,5 +79,5 @@
 		goto out;
 	
-	rc = REGISTER_ME(SERVICE_ARP, &phonehash);
+	rc = ipc_connect_to_me(PHONE_NS, SERVICE_ARP, 0, 0, &phonehash);
 	if (rc != EOK)
 		goto out;
Index: uspace/srv/net/il/ip/ip.c
===================================================================
--- uspace/srv/net/il/ip/ip.c	(revision 6e5dc07f868b16c838c79bc42117b6116010e91b)
+++ uspace/srv/net/il/ip/ip.c	(revision f568ee7ca6382a57f76ee8c0cb5ff31f8955baf1)
@@ -442,5 +442,5 @@
 		if (route) {
 			address.value = (char *) &route->address.s_addr;
-			address.length = CONVERT_SIZE(in_addr_t, char, 1);
+			address.length = sizeof(in_addr_t);
 			
 			rc = arp_device_req(ip_netif->arp->phone,
@@ -639,5 +639,5 @@
 	if (destination) {
 		rc = packet_set_addr(packet, NULL, (uint8_t *) destination->value,
-		    CONVERT_SIZE(char, uint8_t, destination->length));
+		    destination->length);
 	} else {
 		rc = packet_set_addr(packet, NULL, NULL, 0);
@@ -687,6 +687,5 @@
 				rc = packet_set_addr(next, NULL,
 				    (uint8_t *) destination->value,
-				    CONVERT_SIZE(char, uint8_t,
-				    destination->length));
+				    destination->length);
 				if (rc != EOK) {
 				    	free(last_header);
@@ -718,5 +717,5 @@
 			rc = packet_set_addr(next, NULL,
 			    (uint8_t *) destination->value,
-			    CONVERT_SIZE(char, uint8_t, destination->length));
+			    destination->length);
 			if (rc != EOK) {
 				free(last_header);
@@ -1006,5 +1005,5 @@
 		destination.value = route->gateway.s_addr ?
 		    (char *) &route->gateway.s_addr : (char *) &dest.s_addr;
-		destination.length = CONVERT_SIZE(dest.s_addr, char, 1);
+		destination.length = sizeof(dest.s_addr);
 
 		rc = arp_translate_req(netif->arp->phone, netif->device_id,
@@ -1758,6 +1757,5 @@
 			// clear the ARP mapping if any
 			address.value = (char *) &header->destination_address;
-			address.length = CONVERT_SIZE(uint8_t, char,
-			    sizeof(header->destination_address));
+			address.length = sizeof(header->destination_address);
 			arp_clear_address_req(netif->arp->phone,
 			    netif->device_id, SERVICE_IP, &address);
@@ -1951,5 +1949,6 @@
 
 	case NET_IP_GET_ROUTE:
-		rc = data_receive((void **) &addr, &addrlen);
+		rc = async_data_write_accept((void **) &addr, false, 0, 0, 0,
+		    &addrlen);
 		if (rc != EOK)
 			return rc;
Index: uspace/srv/net/il/ip/ip_module.c
===================================================================
--- uspace/srv/net/il/ip/ip_module.c	(revision 6e5dc07f868b16c838c79bc42117b6116010e91b)
+++ uspace/srv/net/il/ip/ip_module.c	(revision f568ee7ca6382a57f76ee8c0cb5ff31f8955baf1)
@@ -80,5 +80,5 @@
 		goto out;
 	
-	rc = REGISTER_ME(SERVICE_IP, &phonehash);
+	rc = ipc_connect_to_me(PHONE_NS, SERVICE_IP, 0, 0, &phonehash);
 	if (rc != EOK)
 		goto out;
Index: uspace/srv/net/net/net.c
===================================================================
--- uspace/srv/net/net/net.c	(revision 6e5dc07f868b16c838c79bc42117b6116010e91b)
+++ uspace/srv/net/net/net.c	(revision f568ee7ca6382a57f76ee8c0cb5ff31f8955baf1)
@@ -335,5 +335,5 @@
 		goto out;
 	
-	rc = REGISTER_ME(SERVICE_NETWORKING, &phonehash);
+	rc = ipc_connect_to_me(PHONE_NS, SERVICE_NETWORKING, 0, 0, &phonehash);
 	if (rc != EOK)
 		goto out;
Index: uspace/srv/net/netif/lo/lo.c
===================================================================
--- uspace/srv/net/netif/lo/lo.c	(revision 6e5dc07f868b16c838c79bc42117b6116010e91b)
+++ uspace/srv/net/netif/lo/lo.c	(revision f568ee7ca6382a57f76ee8c0cb5ff31f8955baf1)
@@ -166,5 +166,5 @@
 	sysarg_t phonehash;
 
-	return REGISTER_ME(SERVICE_LO, &phonehash);
+	return ipc_connect_to_me(PHONE_NS, SERVICE_LO, 0, 0, &phonehash);
 }
 
Index: uspace/srv/net/nil/eth/eth.c
===================================================================
--- uspace/srv/net/nil/eth/eth.c	(revision 6e5dc07f868b16c838c79bc42117b6116010e91b)
+++ uspace/srv/net/nil/eth/eth.c	(revision f568ee7ca6382a57f76ee8c0cb5ff31f8955baf1)
@@ -201,6 +201,5 @@
 
 	eth_globals.broadcast_addr =
-	    measured_string_create_bulk("\xFF\xFF\xFF\xFF\xFF\xFF",
-	    CONVERT_SIZE(uint8_t, char, ETH_ADDR));
+	    measured_string_create_bulk("\xFF\xFF\xFF\xFF\xFF\xFF", ETH_ADDR);
 	if (!eth_globals.broadcast_addr) {
 		rc = ENOMEM;
Index: uspace/srv/net/nil/eth/eth_module.c
===================================================================
--- uspace/srv/net/nil/eth/eth_module.c	(revision 6e5dc07f868b16c838c79bc42117b6116010e91b)
+++ uspace/srv/net/nil/eth/eth_module.c	(revision f568ee7ca6382a57f76ee8c0cb5ff31f8955baf1)
@@ -66,5 +66,5 @@
 		goto out;
 
-	rc = REGISTER_ME(SERVICE_ETHERNET, &phonehash);
+	rc = ipc_connect_to_me(PHONE_NS, SERVICE_ETHERNET, 0, 0, &phonehash);
 	if (rc != EOK)
 		goto out;
Index: uspace/srv/net/nil/nildummy/nildummy_module.c
===================================================================
--- uspace/srv/net/nil/nildummy/nildummy_module.c	(revision 6e5dc07f868b16c838c79bc42117b6116010e91b)
+++ uspace/srv/net/nil/nildummy/nildummy_module.c	(revision f568ee7ca6382a57f76ee8c0cb5ff31f8955baf1)
@@ -67,5 +67,5 @@
 		goto out;
 	
-	rc = REGISTER_ME(SERVICE_NILDUMMY, &phonehash);
+	rc = ipc_connect_to_me(PHONE_NS, SERVICE_NILDUMMY, 0, 0, &phonehash);
 	if (rc != EOK)
 		goto out;
Index: uspace/srv/net/tl/icmp/icmp_module.c
===================================================================
--- uspace/srv/net/tl/icmp/icmp_module.c	(revision 6e5dc07f868b16c838c79bc42117b6116010e91b)
+++ uspace/srv/net/tl/icmp/icmp_module.c	(revision f568ee7ca6382a57f76ee8c0cb5ff31f8955baf1)
@@ -74,5 +74,5 @@
 		goto out;
 
-	rc = REGISTER_ME(SERVICE_ICMP, &phonehash);
+	rc = ipc_connect_to_me(PHONE_NS, SERVICE_ICMP, 0, 0, &phonehash);
 	if (rc != EOK)
 		goto out;
Index: uspace/srv/net/tl/tcp/tcp.c
===================================================================
--- uspace/srv/net/tl/tcp/tcp.c	(revision 6e5dc07f868b16c838c79bc42117b6116010e91b)
+++ uspace/srv/net/tl/tcp/tcp.c	(revision f568ee7ca6382a57f76ee8c0cb5ff31f8955baf1)
@@ -1365,5 +1365,6 @@
 
 		case NET_SOCKET_BIND:
-			res = data_receive((void **) &addr, &addrlen);
+			res = async_data_write_accept((void **) &addr, false,
+			    0, 0, 0, &addrlen);
 			if (res != EOK)
 				break;
@@ -1402,5 +1403,6 @@
 
 		case NET_SOCKET_CONNECT:
-			res = data_receive((void **) &addr, &addrlen);
+			res = async_data_write_accept((void **) &addr, false,
+			    0, 0, 0, &addrlen);
 			if (res != EOK)
 				break;
@@ -1453,5 +1455,6 @@
 
 		case NET_SOCKET_SENDTO:
-			res = data_receive((void **) &addr, &addrlen);
+			res = async_data_write_accept((void **) &addr, false,
+			    0, 0, 0, &addrlen);
 			if (res != EOK)
 				break;
Index: uspace/srv/net/tl/tcp/tcp_module.c
===================================================================
--- uspace/srv/net/tl/tcp/tcp_module.c	(revision 6e5dc07f868b16c838c79bc42117b6116010e91b)
+++ uspace/srv/net/tl/tcp/tcp_module.c	(revision f568ee7ca6382a57f76ee8c0cb5ff31f8955baf1)
@@ -75,5 +75,5 @@
 		goto out;
 
-	rc = REGISTER_ME(SERVICE_TCP, &phonehash);
+	rc = ipc_connect_to_me(PHONE_NS, SERVICE_TCP, 0, 0, &phonehash);
 	if (rc != EOK)
 		goto out;
Index: uspace/srv/net/tl/udp/udp.c
===================================================================
--- uspace/srv/net/tl/udp/udp.c	(revision 6e5dc07f868b16c838c79bc42117b6116010e91b)
+++ uspace/srv/net/tl/udp/udp.c	(revision f568ee7ca6382a57f76ee8c0cb5ff31f8955baf1)
@@ -771,5 +771,6 @@
 
 		case NET_SOCKET_BIND:
-			res = data_receive((void **) &addr, &addrlen);
+			res = async_data_write_accept((void **) &addr, false,
+			    0, 0, 0, &addrlen);
 			if (res != EOK)
 				break;
@@ -784,5 +785,6 @@
 
 		case NET_SOCKET_SENDTO:
-			res = data_receive((void **) &addr, &addrlen);
+			res = async_data_write_accept((void **) &addr, false,
+			    0, 0, 0, &addrlen);
 			if (res != EOK)
 				break;
Index: uspace/srv/net/tl/udp/udp_module.c
===================================================================
--- uspace/srv/net/tl/udp/udp_module.c	(revision 6e5dc07f868b16c838c79bc42117b6116010e91b)
+++ uspace/srv/net/tl/udp/udp_module.c	(revision f568ee7ca6382a57f76ee8c0cb5ff31f8955baf1)
@@ -75,5 +75,5 @@
 		goto out;
 	
-	rc = REGISTER_ME(SERVICE_UDP, &phonehash);
+	rc = ipc_connect_to_me(PHONE_NS, SERVICE_UDP, 0, 0, &phonehash);
 	if (rc != EOK)
 		goto out;
