Index: uspace/drv/root/root/Makefile
===================================================================
--- uspace/drv/root/root/Makefile	(revision 2a37b9f1eb93bba78ec231d42ef29f30dff550a0)
+++ uspace/drv/root/root/Makefile	(revision 2a37b9f1eb93bba78ec231d42ef29f30dff550a0)
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2010 Lenka Trochtova
+# 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.
+#
+
+USPACE_PREFIX = ../../..
+LIBS = $(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
+BINARY = root
+
+SOURCES = \
+	root.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/root/root/root.c
===================================================================
--- uspace/drv/root/root/root.c	(revision 2a37b9f1eb93bba78ec231d42ef29f30dff550a0)
+++ uspace/drv/root/root/root.c	(revision 2a37b9f1eb93bba78ec231d42ef29f30dff550a0)
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2010 Lenka Trochtova
+ * Copyright (c) 2010 Vojtech Horky
+ * Copyright (c) 2011 Jiri Svoboda
+ * 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.
+ */
+
+/**
+ * @defgroup root Root device driver.
+ * @brief HelenOS root device driver.
+ * @{
+ */
+
+/** @file
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <fibril_synch.h>
+#include <stdlib.h>
+#include <str.h>
+#include <str_error.h>
+#include <ctype.h>
+#include <macros.h>
+#include <inttypes.h>
+#include <sysinfo.h>
+
+#include <ddf/driver.h>
+#include <ddf/log.h>
+
+#define NAME "root"
+
+#define PLATFORM_FUN_NAME "hw"
+#define PLATFORM_FUN_MATCH_ID_FMT "platform/%s"
+#define PLATFORM_FUN_MATCH_SCORE 100
+
+#define VIRTUAL_FUN_NAME "virt"
+#define VIRTUAL_FUN_MATCH_ID "virt"
+#define VIRTUAL_FUN_MATCH_SCORE 100
+
+static int root_dev_add(ddf_dev_t *dev);
+static int root_fun_online(ddf_fun_t *fun);
+static int root_fun_offline(ddf_fun_t *fun);
+
+/** The root device driver's standard operations. */
+static driver_ops_t root_ops = {
+	.dev_add = &root_dev_add,
+	.fun_online = &root_fun_online,
+	.fun_offline = &root_fun_offline
+};
+
+/** The root device driver structure. */
+static driver_t root_driver = {
+	.name = NAME,
+	.driver_ops = &root_ops
+};
+
+/** Create the function which represents the root of virtual device tree.
+ *
+ * @param dev	Device
+ * @return	EOK on success or negative error code
+ */
+static int add_virtual_root_fun(ddf_dev_t *dev)
+{
+	const char *name = VIRTUAL_FUN_NAME;
+	ddf_fun_t *fun;
+	int rc;
+
+	ddf_msg(LVL_DEBUG, "Adding new function for virtual devices. "
+	    "Function node is `%s' (%d %s)", name,
+	    VIRTUAL_FUN_MATCH_SCORE, VIRTUAL_FUN_MATCH_ID);
+
+	fun = ddf_fun_create(dev, fun_inner, name);
+	if (fun == NULL) {
+		ddf_msg(LVL_ERROR, "Failed creating function %s", name);
+		return ENOMEM;
+	}
+
+	rc = ddf_fun_add_match_id(fun, VIRTUAL_FUN_MATCH_ID,
+	    VIRTUAL_FUN_MATCH_SCORE);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed adding match IDs to function %s",
+		    name);
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed binding function %s: %s", name,
+		    str_error(rc));
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	return EOK;
+}
+
+/** Create the function which represents the root of HW device tree.
+ *
+ * @param dev	Device
+ * @return	EOK on success or negative error code
+ */
+static int add_platform_fun(ddf_dev_t *dev)
+{
+	char *match_id;
+	char *platform;
+	size_t platform_size;
+
+	const char *name = PLATFORM_FUN_NAME;
+	ddf_fun_t *fun;
+	int rc;
+
+	/* Get platform name from sysinfo. */
+	platform = sysinfo_get_data("platform", &platform_size);
+	if (platform == NULL) {
+		ddf_msg(LVL_ERROR, "Failed to obtain platform name.");
+		return ENOENT;
+	}
+
+	/* Null-terminate string. */
+	platform = realloc(platform, platform_size + 1);
+	if (platform == NULL) {
+		ddf_msg(LVL_ERROR, "Memory allocation failed.");
+		return ENOMEM;
+	}
+
+	platform[platform_size] = '\0';
+
+	/* Construct match ID. */
+	if (asprintf(&match_id, PLATFORM_FUN_MATCH_ID_FMT, platform) == -1) {
+		ddf_msg(LVL_ERROR, "Memory allocation failed.");
+		free(platform);
+		return ENOMEM;
+	}
+
+	free(platform);
+
+	/* Add function. */
+	ddf_msg(LVL_DEBUG, "Adding platform function. Function node is `%s' "
+	    " (%d %s)", PLATFORM_FUN_NAME, PLATFORM_FUN_MATCH_SCORE,
+	    match_id);
+
+	fun = ddf_fun_create(dev, fun_inner, name);
+	if (fun == NULL) {
+		ddf_msg(LVL_ERROR, "Error creating function %s", name);
+		free(match_id);
+		return ENOMEM;
+	}
+
+	rc = ddf_fun_add_match_id(fun, match_id, PLATFORM_FUN_MATCH_SCORE);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed adding match IDs to function %s",
+		    name);
+		free(match_id);
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	free(match_id);
+
+	rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed binding function %s: %s", name,
+		    str_error(rc));
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	return EOK;
+}
+
+/** Get the root device.
+ *
+ * @param dev		The device which is root of the whole device tree (both
+ *			of HW and pseudo devices).
+ */
+static int root_dev_add(ddf_dev_t *dev)
+{
+	ddf_msg(LVL_DEBUG, "root_dev_add, device handle=%" PRIun,
+	    ddf_dev_get_handle(dev));
+
+	/*
+	 * Register virtual devices root.
+	 * We warn on error occurrence because virtual devices shall not be
+	 * vital for the system.
+	 */
+	int res = add_virtual_root_fun(dev);
+	if (res != EOK)
+		ddf_msg(LVL_WARN, "Failed to add virtual child.");
+
+	/* Register root device's children. */
+	res = add_platform_fun(dev);
+	if (EOK != res)
+		ddf_msg(LVL_ERROR, "Failed adding child device for platform.");
+
+	return res;
+}
+
+static int root_fun_online(ddf_fun_t *fun)
+{
+	ddf_msg(LVL_DEBUG, "root_fun_online()");
+	return ddf_fun_online(fun);
+}
+
+static int root_fun_offline(ddf_fun_t *fun)
+{
+	ddf_msg(LVL_DEBUG, "root_fun_offline()");
+	return ddf_fun_offline(fun);
+}
+
+int main(int argc, char *argv[])
+{
+	printf(NAME ": HelenOS root device driver\n");
+
+	ddf_log_init(NAME);
+	return ddf_driver_main(&root_driver);
+}
+
+/**
+ * @}
+ */
+
Index: uspace/drv/root/root/root.ma
===================================================================
--- uspace/drv/root/root/root.ma	(revision 2a37b9f1eb93bba78ec231d42ef29f30dff550a0)
+++ uspace/drv/root/root/root.ma	(revision 2a37b9f1eb93bba78ec231d42ef29f30dff550a0)
@@ -0,0 +1,1 @@
+10 root
Index: uspace/drv/root/virt/Makefile
===================================================================
--- uspace/drv/root/virt/Makefile	(revision 2a37b9f1eb93bba78ec231d42ef29f30dff550a0)
+++ uspace/drv/root/virt/Makefile	(revision 2a37b9f1eb93bba78ec231d42ef29f30dff550a0)
@@ -0,0 +1,37 @@
+#
+# 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.
+#
+
+USPACE_PREFIX = ../../..
+LIBS = $(LIBDRV_PREFIX)/libdrv.a
+EXTRA_CFLAGS += -I$(LIBDRV_PREFIX)/include
+BINARY = virt
+
+SOURCES = \
+	virt.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/root/virt/devices.def
===================================================================
--- uspace/drv/root/virt/devices.def	(revision 2a37b9f1eb93bba78ec231d42ef29f30dff550a0)
+++ uspace/drv/root/virt/devices.def	(revision 2a37b9f1eb93bba78ec231d42ef29f30dff550a0)
@@ -0,0 +1,46 @@
+/*
+ * Add list of virtual devices you want to launch driver for here.
+ *
+ * Unless the list is empty, the last item shall be followed by a comma.
+ */
+
+/* Kernel framebuffer */
+{
+    .name = "kfb",
+    .match_id = "virtual&kfb"
+},
+
+#ifdef CONFIG_TEST_DRIVERS
+
+{
+	.name = "test1",
+	.match_id = "virtual&test1"
+},
+{
+	.name = "test2alpha",
+	.match_id = "virtual&test2"
+},
+{
+	.name = "test2bravo",
+	.match_id = "virtual&test2"
+},
+{
+	.name = "null",
+	.match_id = "virtual&test1"
+},
+{
+	.name = "test3",
+	.match_id = "virtual&test3"
+},
+
+#endif
+
+#ifdef CONFIG_RUN_VIRTUAL_USB_HC
+
+/* Virtual USB host controller. */
+{
+	.name = "usbhc",
+	.match_id = "usb&hc=vhc"
+},
+
+#endif
Index: uspace/drv/root/virt/virt.c
===================================================================
--- uspace/drv/root/virt/virt.c	(revision 2a37b9f1eb93bba78ec231d42ef29f30dff550a0)
+++ uspace/drv/root/virt/virt.c	(revision 2a37b9f1eb93bba78ec231d42ef29f30dff550a0)
@@ -0,0 +1,249 @@
+/*
+ * 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.
+ */
+
+/**
+ * @defgroup virt Root device driver for virtual devices.
+ * @{
+ */
+
+/** @file
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <errno.h>
+#include <str_error.h>
+#include <ddf/driver.h>
+#include <ddf/log.h>
+
+#define NAME "virt"
+
+/** Virtual function entry */
+typedef struct {
+	/** Function name */
+	const char *name;
+	/** Function match ID */
+	const char *match_id;
+} virtual_function_t;
+
+/** List of existing virtual functions */
+virtual_function_t virtual_functions[] = {
+#include "devices.def"
+	/* Terminating item */
+	{
+		.name = NULL,
+		.match_id = NULL
+	}
+};
+
+static int virt_dev_add(ddf_dev_t *dev);
+static int virt_dev_remove(ddf_dev_t *dev);
+static int virt_fun_online(ddf_fun_t *fun);
+static int virt_fun_offline(ddf_fun_t *fun);
+
+static driver_ops_t virt_ops = {
+	.dev_add = &virt_dev_add,
+	.dev_remove = &virt_dev_remove,
+	.fun_online = &virt_fun_online,
+	.fun_offline = &virt_fun_offline
+};
+
+static driver_t virt_driver = {
+	.name = NAME,
+	.driver_ops = &virt_ops
+};
+
+/* Device soft state */
+typedef struct {
+	ddf_dev_t *dev;
+	list_t functions;
+} virt_t;
+
+/* Function soft state */
+typedef struct {
+	ddf_fun_t *fun;
+	link_t dev_link;
+} virt_fun_t;
+
+static int instances = 0;
+
+
+/** Add function to the virtual device.
+ *
+ * @param vdev		The virtual device
+ * @param vfun		Virtual function description
+ * @return		EOK on success or negative error code.
+ */
+static int virt_add_fun(virt_t *virt, virtual_function_t *vfun)
+{
+	ddf_dev_t *vdev = virt->dev;
+	ddf_fun_t *fun;
+	virt_fun_t *rvfun;
+	int rc;
+
+	ddf_msg(LVL_DEBUG, "Registering function `%s' (match \"%s\")",
+	    vfun->name, vfun->match_id);
+
+	fun = ddf_fun_create(vdev, fun_inner, vfun->name);
+	if (fun == NULL) {
+		ddf_msg(LVL_ERROR, "Failed creating function %s", vfun->name);
+		return ENOMEM;
+	}
+
+	rvfun = ddf_fun_data_alloc(fun, sizeof(virt_fun_t));
+	if (rvfun == NULL) {
+		ddf_msg(LVL_ERROR, "Failed allocating soft state for %s.",
+		    vfun->name);
+		ddf_fun_destroy(fun);
+		return ENOMEM;
+	}
+
+	rvfun->fun = fun;
+
+	rc = ddf_fun_add_match_id(fun, vfun->match_id, 10);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed adding match IDs to function %s",
+		    vfun->name);
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed binding function %s: %s",
+		    vfun->name, str_error(rc));
+		ddf_fun_destroy(fun);
+		return rc;
+	}
+
+	list_append(&rvfun->dev_link, &virt->functions);
+
+	ddf_msg(LVL_NOTE, "Registered child device `%s'", vfun->name);
+	return EOK;
+}
+
+static int virt_fun_remove(virt_fun_t *rvfun)
+{
+	int rc;
+	const char *name = ddf_fun_get_name(rvfun->fun);
+
+	ddf_msg(LVL_DEBUG, "virt_fun_remove('%s')", name);
+	rc = ddf_fun_offline(rvfun->fun);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Error offlining function '%s'.", name);
+		return rc;
+	}
+
+	rc = ddf_fun_unbind(rvfun->fun);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed unbinding function '%s'.", name);
+		return rc;
+	}
+
+	list_remove(&rvfun->dev_link);
+	ddf_fun_destroy(rvfun->fun);
+	return EOK;
+}
+
+
+static int virt_dev_add(ddf_dev_t *dev)
+{
+	virt_t *virt;
+
+	/*
+	 * Allow only single instance of root virtual device.
+	 */
+	if (++instances > 1) {
+		return ELIMIT;
+	}
+
+	ddf_msg(LVL_DEBUG, "dev_add(handle=%d)", (int)ddf_dev_get_handle(dev));
+
+	virt = ddf_dev_data_alloc(dev, sizeof(virt_t));
+	if (virt == NULL)
+		return ENOMEM;
+
+	virt->dev = dev;
+	list_initialize(&virt->functions);
+
+	/*
+	 * Go through all virtual functions and try to add them.
+	 * We silently ignore failures.
+	 */
+	virtual_function_t *vfun = virtual_functions;
+	while (vfun->name != NULL) {
+		(void) virt_add_fun(virt, vfun);
+		vfun++;
+	}
+
+	return EOK;
+}
+
+static int virt_dev_remove(ddf_dev_t *dev)
+{
+	virt_t *virt = (virt_t *)ddf_dev_data_get(dev);
+	int rc;
+
+	while (!list_empty(&virt->functions)) {
+		virt_fun_t *rvfun = list_get_instance(
+		    list_first(&virt->functions), virt_fun_t,
+			dev_link);
+
+		rc = virt_fun_remove(rvfun);
+		if (rc != EOK)
+			return rc;
+	}
+
+	--instances;
+	return EOK;
+}
+
+static int virt_fun_online(ddf_fun_t *fun)
+{
+	ddf_msg(LVL_DEBUG, "virt_fun_online()");
+	return ddf_fun_online(fun);
+}
+
+static int virt_fun_offline(ddf_fun_t *fun)
+{
+	ddf_msg(LVL_DEBUG, "virt_fun_offline()");
+	return ddf_fun_offline(fun);
+}
+
+int main(int argc, char *argv[])
+{
+	printf(NAME ": HelenOS virtual devices root driver\n");
+
+	ddf_log_init(NAME);
+	return ddf_driver_main(&virt_driver);
+}
+
+/**
+ * @}
+ */
+
Index: uspace/drv/root/virt/virt.ma
===================================================================
--- uspace/drv/root/virt/virt.ma	(revision 2a37b9f1eb93bba78ec231d42ef29f30dff550a0)
+++ uspace/drv/root/virt/virt.ma	(revision 2a37b9f1eb93bba78ec231d42ef29f30dff550a0)
@@ -0,0 +1,1 @@
+10 virt
