Index: uspace/drv/infrastructure/rootvirt/rootvirt.c
===================================================================
--- uspace/drv/infrastructure/rootvirt/rootvirt.c	(revision 1dc4a5e441cc195a33bd958ea4994dcd59141df0)
+++ uspace/drv/infrastructure/rootvirt/rootvirt.c	(revision 1a5b2521ea58a25aa1f13d0850fa06ae93fba965)
@@ -63,7 +63,11 @@
 
 static int rootvirt_add_device(ddf_dev_t *dev);
+static int rootvirt_fun_online(ddf_fun_t *fun);
+static int rootvirt_fun_offline(ddf_fun_t *fun);
 
 static driver_ops_t rootvirt_ops = {
-	.add_device = &rootvirt_add_device
+	.add_device = &rootvirt_add_device,
+	.fun_online = &rootvirt_fun_online,
+	.fun_offline = &rootvirt_fun_offline
 };
 
@@ -140,4 +144,16 @@
 }
 
+static int rootvirt_fun_online(ddf_fun_t *fun)
+{
+	ddf_msg(LVL_DEBUG, "rootvirt_fun_online()");
+	return ddf_fun_online(fun);
+}
+
+static int rootvirt_fun_offline(ddf_fun_t *fun)
+{
+	ddf_msg(LVL_DEBUG, "rootvirt_fun_offline()");
+	return ddf_fun_offline(fun);
+}
+
 int main(int argc, char *argv[])
 {
Index: uspace/drv/test/test1/test1.c
===================================================================
--- uspace/drv/test/test1/test1.c	(revision 1dc4a5e441cc195a33bd958ea4994dcd59141df0)
+++ uspace/drv/test/test1/test1.c	(revision 1a5b2521ea58a25aa1f13d0850fa06ae93fba965)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2010 Vojtech Horky
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -40,7 +41,13 @@
 
 static int test1_add_device(ddf_dev_t *dev);
+static int test1_dev_remove(ddf_dev_t *dev);
+static int test1_fun_online(ddf_fun_t *fun);
+static int test1_fun_offline(ddf_fun_t *fun);
 
 static driver_ops_t driver_ops = {
-	.add_device = &test1_add_device
+	.add_device = &test1_add_device,
+	.dev_remove = &test1_dev_remove,
+	.fun_online = &test1_fun_online,
+	.fun_offline = &test1_fun_offline
 };
 
@@ -49,4 +56,10 @@
 	.driver_ops = &driver_ops
 };
+
+typedef struct {
+	ddf_fun_t *fun_a;
+	ddf_fun_t *clone;
+	ddf_fun_t *child;
+} test1_t;
 
 /** Register child and inform user about it.
@@ -60,5 +73,5 @@
 static int register_fun_verbose(ddf_dev_t *parent, const char *message,
     const char *name, const char *match_id, int match_score,
-    int expected_rc)
+    int expected_rc, ddf_fun_t **pfun)
 {
 	ddf_fun_t *fun = NULL;
@@ -103,4 +116,7 @@
 	}
 
+	if (pfun != NULL)
+		*pfun = fun;
+
 	return rc;
 }
@@ -126,8 +142,15 @@
 {
 	ddf_fun_t *fun_a;
+	test1_t *test1;
 	int rc;
 
 	ddf_msg(LVL_DEBUG, "add_device(name=\"%s\", handle=%d)",
 	    dev->name, (int) dev->handle);
+
+	test1 = calloc(1, sizeof(test1_t));
+	if (test1 == NULL) {
+		ddf_msg(LVL_ERROR, "Failed allocating softstate.\n");
+		return ENOMEM;
+	}
 
 	fun_a = ddf_fun_create(dev, fun_exposed, "a");
@@ -140,4 +163,5 @@
 	if (rc != EOK) {
 		ddf_msg(LVL_ERROR, "Failed binding function 'a'.");
+		ddf_fun_destroy(fun_a);
 		return rc;
 	}
@@ -151,17 +175,80 @@
 		(void) register_fun_verbose(dev,
 		    "cloning myself ;-)", "clone",
-		    "virtual&test1", 10, EOK);
+		    "virtual&test1", 10, EOK, &test1->clone);
 		(void) register_fun_verbose(dev,
 		    "cloning myself twice ;-)", "clone",
-		    "virtual&test1", 10, EEXISTS);
+		    "virtual&test1", 10, EEXISTS, NULL);
 	} else if (str_cmp(dev->name, "clone") == 0) {
 		(void) register_fun_verbose(dev,
 		    "run by the same task", "child",
-		    "virtual&test1&child", 10, EOK);
+		    "virtual&test1&child", 10, EOK, &test1->child);
 	}
 
 	ddf_msg(LVL_DEBUG, "Device `%s' accepted.", dev->name);
 
+	test1->fun_a = fun_a;
+	dev->driver_data = test1;
 	return EOK;
+}
+
+static int fun_remove(ddf_fun_t *fun, const char *name)
+{
+	int rc;
+
+	ddf_msg(LVL_DEBUG, "fun_remove(%p, '%s')\n", fun, name);
+	rc = ddf_fun_offline(fun);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Error offlining function '%s'.", name);
+		return rc;
+	}
+
+	rc = ddf_fun_unbind(fun);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed offlining function '%s'.", name);
+		return rc;
+	}
+
+	ddf_fun_destroy(fun);
+	return EOK;
+}
+
+static int test1_dev_remove(ddf_dev_t *dev)
+{
+	test1_t *test1 = (test1_t *)dev->driver_data;
+	int rc;
+
+	ddf_msg(LVL_DEBUG, "test1_dev_remove(%p)", dev);
+
+	if (test1->fun_a != NULL) {
+		rc = fun_remove(test1->fun_a, "a");
+		if (rc != EOK)
+			return rc;
+	}
+
+	if (test1->clone != NULL) {
+		rc = fun_remove(test1->clone, "clone");
+		if (rc != EOK)
+			return rc;
+	}
+
+	if (test1->child != NULL) {
+		rc = fun_remove(test1->child, "child");
+		if (rc != EOK)
+			return rc;
+	}
+
+	return EOK;
+}
+
+static int test1_fun_online(ddf_fun_t *fun)
+{
+	ddf_msg(LVL_DEBUG, "test1_fun_online()");
+	return ddf_fun_online(fun);
+}
+
+static int test1_fun_offline(ddf_fun_t *fun)
+{
+	ddf_msg(LVL_DEBUG, "test1_fun_offline()");
+	return ddf_fun_offline(fun);
 }
 
