Index: uspace/lib/c/generic/devman.c
===================================================================
--- uspace/lib/c/generic/devman.c	(revision 36e2b55baba3a1dca2bdc60427e16d91cdffae3f)
+++ uspace/lib/c/generic/devman.c	(revision 8cc4ddbbba9660f305e4757b551bf1d9545609b3)
@@ -327,4 +327,28 @@
 }
 
+int devman_drv_fun_online(devman_handle_t funh)
+{
+	async_exch_t *exch = devman_exchange_begin(DEVMAN_DRIVER);
+	if (exch == NULL)
+		return ENOMEM;
+	
+	sysarg_t retval = async_req_1_0(exch, DEVMAN_DRV_FUN_ONLINE, funh);
+	
+	devman_exchange_end(exch);
+	return (int) retval;
+}
+
+int devman_drv_fun_offline(devman_handle_t funh)
+{
+	async_exch_t *exch = devman_exchange_begin(DEVMAN_DRIVER);
+	if (exch == NULL)
+		return ENOMEM;
+	
+	sysarg_t retval = async_req_1_0(exch, DEVMAN_DRV_FUN_OFFLINE, funh);
+	
+	devman_exchange_end(exch);
+	return (int) retval;
+}
+
 async_sess_t *devman_parent_device_connect(exch_mgmt_t mgmt,
     devman_handle_t handle, unsigned int flags)
@@ -430,4 +454,28 @@
 }
 
+int devman_fun_online(devman_handle_t funh)
+{
+	async_exch_t *exch = devman_exchange_begin(DEVMAN_CLIENT);
+	if (exch == NULL)
+		return ENOMEM;
+	
+	sysarg_t retval = async_req_1_0(exch, DEVMAN_FUN_ONLINE, funh);
+	
+	devman_exchange_end(exch);
+	return (int) retval;
+}
+
+int devman_fun_offline(devman_handle_t funh)
+{
+	async_exch_t *exch = devman_exchange_begin(DEVMAN_CLIENT);
+	if (exch == NULL)
+		return ENOMEM;
+	
+	sysarg_t retval = async_req_1_0(exch, DEVMAN_FUN_OFFLINE, funh);
+	
+	devman_exchange_end(exch);
+	return (int) retval;
+}
+
 static int devman_get_handles_once(sysarg_t method, sysarg_t arg1,
     devman_handle_t *handle_buf, size_t buf_size, size_t *act_size)
Index: uspace/lib/c/include/devman.h
===================================================================
--- uspace/lib/c/include/devman.h	(revision 36e2b55baba3a1dca2bdc60427e16d91cdffae3f)
+++ uspace/lib/c/include/devman.h	(revision 8cc4ddbbba9660f305e4757b551bf1d9545609b3)
@@ -50,4 +50,6 @@
     devman_handle_t, devman_handle_t *);
 extern int devman_remove_function(devman_handle_t);
+extern int devman_drv_fun_online(devman_handle_t);
+extern int devman_drv_fun_offline(devman_handle_t);
 
 extern async_sess_t *devman_device_connect(exch_mgmt_t, devman_handle_t,
@@ -63,4 +65,6 @@
 extern int devman_fun_get_name(devman_handle_t, char *, size_t);
 extern int devman_fun_get_path(devman_handle_t, char *, size_t);
+extern int devman_fun_online(devman_handle_t);
+extern int devman_fun_offline(devman_handle_t);
 
 extern int devman_add_device_to_category(devman_handle_t, const char *);
Index: uspace/lib/c/include/ipc/devman.h
===================================================================
--- uspace/lib/c/include/ipc/devman.h	(revision 36e2b55baba3a1dca2bdc60427e16d91cdffae3f)
+++ uspace/lib/c/include/ipc/devman.h	(revision 8cc4ddbbba9660f305e4757b551bf1d9545609b3)
@@ -139,9 +139,14 @@
 	DEVMAN_ADD_MATCH_ID,
 	DEVMAN_ADD_DEVICE_TO_CATEGORY,
+	DEVMAN_DRV_FUN_ONLINE,
+	DEVMAN_DRV_FUN_OFFLINE,
 	DEVMAN_REMOVE_FUNCTION
 } driver_to_devman_t;
 
 typedef enum {
-	DRIVER_ADD_DEVICE = IPC_FIRST_USER_METHOD
+	DRIVER_DEV_ADD = IPC_FIRST_USER_METHOD,
+	DRIVER_DEV_REMOVE,
+	DRIVER_FUN_ONLINE,
+	DRIVER_FUN_OFFLINE,
 
 } devman_to_driver_t;
@@ -152,4 +157,6 @@
 	DEVMAN_FUN_GET_CHILD,
 	DEVMAN_FUN_GET_NAME,
+	DEVMAN_FUN_ONLINE,
+	DEVMAN_FUN_OFFLINE,
 	DEVMAN_FUN_GET_PATH,
 	DEVMAN_FUN_SID_TO_HANDLE
Index: uspace/lib/drv/generic/driver.c
===================================================================
--- uspace/lib/drv/generic/driver.c	(revision 36e2b55baba3a1dca2bdc60427e16d91cdffae3f)
+++ uspace/lib/drv/generic/driver.c	(revision 8cc4ddbbba9660f305e4757b551bf1d9545609b3)
@@ -63,4 +63,8 @@
 
 /** Devices */
+LIST_INITIALIZE(devices);
+FIBRIL_MUTEX_INITIALIZE(devices_mutex);
+
+/** Functions */
 LIST_INITIALIZE(functions);
 FIBRIL_MUTEX_INITIALIZE(functions_mutex);
@@ -227,19 +231,30 @@
 }
 
-static ddf_fun_t *driver_get_function(list_t *functions, devman_handle_t handle)
+static ddf_dev_t *driver_get_device(devman_handle_t handle)
+{
+	ddf_dev_t *dev = NULL;
+	
+	assert(fibril_mutex_is_locked(&devices_mutex));
+	
+	list_foreach(devices, link) {
+		dev = list_get_instance(link, ddf_dev_t, link);
+		if (dev->handle == handle)
+			return dev;
+	}
+	
+	return NULL;
+}
+
+static ddf_fun_t *driver_get_function(devman_handle_t handle)
 {
 	ddf_fun_t *fun = NULL;
 	
-	fibril_mutex_lock(&functions_mutex);
-	
-	list_foreach(*functions, link) {
+	assert(fibril_mutex_is_locked(&functions_mutex));
+	
+	list_foreach(functions, link) {
 		fun = list_get_instance(link, ddf_fun_t, link);
-		if (fun->handle == handle) {
-			fibril_mutex_unlock(&functions_mutex);
+		if (fun->handle == handle)
 			return fun;
-		}
-	}
-	
-	fibril_mutex_unlock(&functions_mutex);
+	}
 	
 	return NULL;
@@ -270,5 +285,86 @@
 		delete_device(dev);
 	
+	fibril_mutex_lock(&devices_mutex);
+	list_append(&dev->link, &devices);
+	fibril_mutex_unlock(&devices_mutex);
+	
 	async_answer_0(iid, res);
+}
+
+static void driver_dev_remove(ipc_callid_t iid, ipc_call_t *icall)
+{
+	devman_handle_t devh;
+	ddf_dev_t *dev;
+	int rc;
+	
+	printf("libdrv: driver_dev_offline()\n");
+	devh = IPC_GET_ARG1(*icall);
+	
+	fibril_mutex_lock(&devices_mutex);
+	dev = driver_get_device(devh);
+	fibril_mutex_unlock(&devices_mutex);
+	/* XXX need lock on dev */
+	
+	if (dev == NULL) {
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	if (driver->driver_ops->dev_remove != NULL)
+		rc = driver->driver_ops->dev_remove(dev);
+	else
+		rc = ENOTSUP;
+	
+	async_answer_0(iid, (sysarg_t) rc);
+}
+
+static void driver_fun_online(ipc_callid_t iid, ipc_call_t *icall)
+{
+	devman_handle_t funh;
+	ddf_fun_t *fun;
+	int rc;
+	
+	funh = IPC_GET_ARG1(*icall);
+	fibril_mutex_lock(&functions_mutex);
+	fun = driver_get_function(funh);
+	fibril_mutex_unlock(&functions_mutex);
+	/* XXX Need lock on fun */
+	
+	if (fun == NULL) {
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	if (driver->driver_ops->fun_online != NULL)
+		rc = driver->driver_ops->fun_online(fun);
+	else
+		rc = ENOTSUP;
+	
+	async_answer_0(iid, (sysarg_t) rc);
+}
+
+static void driver_fun_offline(ipc_callid_t iid, ipc_call_t *icall)
+{
+	devman_handle_t funh;
+	ddf_fun_t *fun;
+	int rc;
+	
+	funh = IPC_GET_ARG1(*icall);
+	fibril_mutex_lock(&functions_mutex);
+	fun = driver_get_function(funh);
+	fibril_mutex_unlock(&functions_mutex);
+	/* XXX Need lock on fun */
+	
+	if (fun == NULL) {
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	if (driver->driver_ops->fun_offline != NULL)
+		rc = driver->driver_ops->fun_offline(fun);
+	else
+		rc = ENOTSUP;
+	
+	async_answer_0(iid, (sysarg_t) rc);
 }
 
@@ -286,9 +382,18 @@
 		
 		switch (IPC_GET_IMETHOD(call)) {
-		case DRIVER_ADD_DEVICE:
+		case DRIVER_DEV_ADD:
 			driver_add_device(callid, &call);
 			break;
+		case DRIVER_DEV_REMOVE:
+			driver_dev_remove(callid, &call);
+			break;
+		case DRIVER_FUN_ONLINE:
+			driver_fun_online(callid, &call);
+			break;
+		case DRIVER_FUN_OFFLINE:
+			driver_fun_offline(callid, &call);
+			break;
 		default:
-			async_answer_0(callid, ENOENT);
+			async_answer_0(callid, ENOTSUP);
 		}
 	}
@@ -308,5 +413,9 @@
 	 */
 	devman_handle_t handle = IPC_GET_ARG2(*icall);
-	ddf_fun_t *fun = driver_get_function(&functions, handle);
+
+	fibril_mutex_lock(&functions_mutex);
+	ddf_fun_t *fun = driver_get_function(handle);
+	fibril_mutex_unlock(&functions_mutex);
+	/* XXX Need a lock on fun */
 	
 	if (fun == NULL) {
@@ -614,5 +723,5 @@
  * the function invisible to the system.
  *
- * @param fun		Function to bind
+ * @param fun		Function to unbind
  * @return		EOK on success or negative error code
  */
@@ -623,5 +732,4 @@
 	assert(fun->bound == true);
 	
-	add_to_functions_list(fun);
 	res = devman_remove_function(fun->handle);
 	if (res != EOK)
@@ -631,4 +739,40 @@
 	
 	fun->bound = false;
+	return EOK;
+}
+
+/** Online function.
+ *
+ * @param fun		Function to online
+ * @return		EOK on success or negative error code
+ */
+int ddf_fun_online(ddf_fun_t *fun)
+{
+	int res;
+	
+	assert(fun->bound == true);
+	
+	res = devman_drv_fun_online(fun->handle);
+	if (res != EOK)
+		return res;
+	
+	return EOK;
+}
+
+/** Offline function.
+ *
+ * @param fun		Function to offline
+ * @return		EOK on success or negative error code
+ */
+int ddf_fun_offline(ddf_fun_t *fun)
+{
+	int res;
+	
+	assert(fun->bound == true);
+	
+	res = devman_drv_fun_offline(fun->handle);
+	if (res != EOK)
+		return res;
+	
 	return EOK;
 }
Index: uspace/lib/drv/include/ddf/driver.h
===================================================================
--- uspace/lib/drv/include/ddf/driver.h	(revision 36e2b55baba3a1dca2bdc60427e16d91cdffae3f)
+++ uspace/lib/drv/include/ddf/driver.h	(revision 8cc4ddbbba9660f305e4757b551bf1d9545609b3)
@@ -132,6 +132,11 @@
 typedef struct driver_ops {
 	/** Callback method for passing a new device to the device driver */
-	int (*add_device)(ddf_dev_t *dev);
-	/* TODO: add other generic driver operations */
+	int (*add_device)(ddf_dev_t *);
+	/** Ask driver to remove a device */
+	int (*dev_remove)(ddf_dev_t *);
+	/** Ask driver to online a specific function */
+	int (*fun_online)(ddf_fun_t *);
+	/** Ask driver to offline a specific function */
+	int (*fun_offline)(ddf_fun_t *);
 } driver_ops_t;
 
@@ -150,4 +155,6 @@
 extern int ddf_fun_bind(ddf_fun_t *);
 extern int ddf_fun_unbind(ddf_fun_t *);
+extern int ddf_fun_online(ddf_fun_t *);
+extern int ddf_fun_offline(ddf_fun_t *);
 extern int ddf_fun_add_match_id(ddf_fun_t *, const char *, int);
 
