Index: uspace/srv/devmap/devmap.c
===================================================================
--- uspace/srv/devmap/devmap.c	(revision 1e4cadad49fbe94a308f6f74c331537fbfc59425)
+++ uspace/srv/devmap/devmap.c	(revision 47a350ff35743ebcc45e185d8b5218aaf60d91ea)
@@ -68,4 +68,18 @@
 } devmap_driver_t;
 
+/** Info about registered namespaces
+ *
+ */
+typedef struct {
+	/** Pointer to the previous and next device in the list of all namespaces */
+	link_t namespaces;
+	/** Unique namespace identifier */
+	dev_handle_t handle;
+	/** Namespace name */
+	char *name;
+	/** Reference count */
+	size_t refcnt;
+} devmap_namespace_t;
+
 /** Info about registered device
  *
@@ -77,6 +91,8 @@
 	    owned by one driver */
 	link_t driver_devices;
-	/** Unique device identifier  */
+	/** Unique device identifier */
 	dev_handle_t handle;
+	/** Device namespace */
+	devmap_namespace_t *namespace;
 	/** Device name */
 	char *name;
@@ -86,4 +102,5 @@
 
 LIST_INITIALIZE(devices_list);
+LIST_INITIALIZE(namespaces_list);
 LIST_INITIALIZE(drivers_list);
 
@@ -117,70 +134,240 @@
 }
 
+/** Convert fully qualified device name to namespace and device name.
+ *
+ * A fully qualified device name can be either a plain device name
+ * (then the namespace is considered to be an empty string) or consist
+ * of two components separated by a slash. No more than one slash
+ * is allowed.
+ *
+ */
+static bool devmap_fqdn_split(const char *fqdn, char **ns_name, char **name)
+{
+	size_t cnt = 0;
+	size_t slash_offset = 0;
+	size_t slash_after = 0;
+	
+	size_t offset = 0;
+	size_t offset_prev = 0;
+	wchar_t c;
+	
+	while ((c = str_decode(fqdn, &offset, STR_NO_LIMIT)) != 0) {
+		if (c == '/') {
+			cnt++;
+			slash_offset = offset_prev;
+			slash_after = offset;
+		}
+		offset_prev = offset;
+	}
+	
+	/* More than one slash */
+	if (cnt > 1)
+		return false;
+	
+	/* No slash -> namespace is empty */
+	if (cnt == 0) {
+		*ns_name = str_dup("");
+		if (*ns_name == NULL)
+			return false;
+		
+		*name = str_dup(fqdn);
+		if ((*name == NULL) || (str_cmp(*name, "") == 0)) {
+			free(*ns_name);
+			return false;
+		}
+		
+		return true;
+	}
+	
+	/* Exactly one slash */
+	*ns_name = str_ndup(fqdn, slash_offset);
+	if (*ns_name == NULL)
+		return false;
+	
+	*name = str_dup(fqdn + slash_after);
+	if ((*name == NULL) || (str_cmp(*name, "") == 0)) {
+		free(*ns_name);
+		return false;
+	}
+	
+	return true;
+}
+
+/** Find namespace with given name.
+ *
+ * The devices_list_mutex should be already held when
+ * calling this function.
+ *
+ */
+static devmap_namespace_t *devmap_namespace_find_name(const char *name)
+{
+	link_t *item = namespaces_list.next;
+	
+	while (item != &namespaces_list) {
+		devmap_namespace_t *namespace = list_get_instance(item, devmap_namespace_t, namespaces);
+		if (str_cmp(namespace->name, name) == 0)
+			return namespace;
+		item = item->next;
+	}
+	
+	return NULL;
+}
+
+/** Find namespace with given handle.
+ *
+ * The devices_list_mutex should be already held when
+ * calling this function.
+ *
+ * @todo: use hash table
+ *
+ */
+static devmap_namespace_t *devmap_namespace_find_handle(dev_handle_t handle)
+{
+	link_t *item = namespaces_list.next;
+	
+	while (item != &namespaces_list) {
+		devmap_namespace_t *namespace = list_get_instance(item, devmap_namespace_t, namespaces);
+		if (namespace->handle == handle)
+			return namespace;
+		
+		item = item->next;
+	}
+	
+	return NULL;
+}
+
 /** Find device with given name.
  *
- */
-static devmap_device_t *devmap_device_find_name(const char *name)
+ * The devices_list_mutex should be already held when
+ * calling this function.
+ *
+ */
+static devmap_device_t *devmap_device_find_name(const char *ns_name,
+    const char *name)
 {
 	link_t *item = devices_list.next;
-	devmap_device_t *device = NULL;
 	
 	while (item != &devices_list) {
-		device = list_get_instance(item, devmap_device_t, devices);
-		if (str_cmp(device->name, name) == 0)
-			break;
+		devmap_device_t *device = list_get_instance(item, devmap_device_t, devices);
+		if ((str_cmp(device->namespace->name, ns_name) == 0) && (str_cmp(device->name, name) == 0))
+			return device;
 		item = item->next;
 	}
 	
-	if (item == &devices_list)
+	return NULL;
+}
+
+/** Find device with given handle.
+ *
+ * The devices_list_mutex should be already held when
+ * calling this function.
+ *
+ * @todo: use hash table
+ *
+ */
+static devmap_device_t *devmap_device_find_handle(dev_handle_t handle)
+{
+	link_t *item = devices_list.next;
+	
+	while (item != &devices_list) {
+		devmap_device_t *device = list_get_instance(item, devmap_device_t, devices);
+		if (device->handle == handle)
+			return device;
+		
+		item = item->next;
+	}
+	
+	return NULL;
+}
+
+/** Create a namespace (if not already present)
+ *
+ * The devices_list_mutex should be already held when
+ * calling this function.
+ *
+ */
+static devmap_namespace_t *devmap_namespace_create(const char *ns_name)
+{
+	devmap_namespace_t *namespace = devmap_namespace_find_name(ns_name);
+	if (namespace != NULL)
+		return namespace;
+	
+	namespace = (devmap_namespace_t *) malloc(sizeof(devmap_namespace_t));
+	if (namespace == NULL)
 		return NULL;
 	
-	device = list_get_instance(item, devmap_device_t, devices);
-	return device;
-}
-
-/** Find device with given handle.
- *
- * @todo: use hash table
- *
- */
-static devmap_device_t *devmap_device_find_handle(dev_handle_t handle)
-{
-	fibril_mutex_lock(&devices_list_mutex);
-	
-	link_t *item = (&devices_list)->next;
-	devmap_device_t *device = NULL;
-	
-	while (item != &devices_list) {
-		device = list_get_instance(item, devmap_device_t, devices);
-		if (device->handle == handle)
-			break;
-		item = item->next;
-	}
-	
-	if (item == &devices_list) {
-		fibril_mutex_unlock(&devices_list_mutex);
+	namespace->name = str_dup(ns_name);
+	if (namespace->name == NULL) {
+		free(namespace);
 		return NULL;
 	}
 	
-	device = list_get_instance(item, devmap_device_t, devices);
-	
-	fibril_mutex_unlock(&devices_list_mutex);
-	
-	return device;
-}
-
-/**
- * Unregister device and free it. It's assumed that driver's device list is
- * already locked.
- */
-static int devmap_device_unregister_core(devmap_device_t *device)
-{
+	namespace->handle = devmap_create_handle();
+	namespace->refcnt = 0;
+	
+	/*
+	 * Insert new namespace into list of registered namespaces
+	 */
+	list_append(&(namespace->namespaces), &namespaces_list);
+	
+	return namespace;
+}
+
+/** Destroy a namespace (if it is no longer needed)
+ *
+ * The devices_list_mutex should be already held when
+ * calling this function.
+ *
+ */
+static void devmap_namespace_destroy(devmap_namespace_t *namespace)
+{
+	if (namespace->refcnt == 0) {
+		list_remove(&(namespace->namespaces));
+		
+		free(namespace->name);
+		free(namespace);
+	}
+}
+
+/** Increase namespace reference count by including device
+ *
+ * The devices_list_mutex should be already held when
+ * calling this function.
+ *
+ */
+static void devmap_namespace_addref(devmap_namespace_t *namespace,
+    devmap_device_t *device)
+{
+	device->namespace = namespace;
+	namespace->refcnt++;
+}
+
+/** Decrease namespace reference count
+ *
+ * The devices_list_mutex should be already held when
+ * calling this function.
+ *
+ */
+static void devmap_namespace_delref(devmap_namespace_t *namespace)
+{
+	namespace->refcnt--;
+	devmap_namespace_destroy(namespace);
+}
+
+/** Unregister device and free it
+ *
+ * The devices_list_mutex should be already held when
+ * calling this function.
+ *
+ */
+static void devmap_device_unregister_core(devmap_device_t *device)
+{
+	devmap_namespace_delref(device->namespace);
 	list_remove(&(device->devices));
 	list_remove(&(device->driver_devices));
 	
+	free(device->namespace);
 	free(device->name);
 	free(device);
-	
-	return EOK;
 }
 
@@ -189,8 +376,6 @@
  * drivers.
  */
-static void devmap_driver_register(devmap_driver_t **odriver)
-{
-	*odriver = NULL;
-	
+static devmap_driver_t *devmap_driver_register(void)
+{
 	ipc_call_t icall;
 	ipc_callid_t iid = async_get_call(&icall);
@@ -198,5 +383,5 @@
 	if (IPC_GET_METHOD(icall) != DEVMAP_DRIVER_REGISTER) {
 		ipc_answer_0(iid, EREFUSED);
-		return;
+		return NULL;
 	}
 	
@@ -205,5 +390,5 @@
 	if (driver == NULL) {
 		ipc_answer_0(iid, ENOMEM);
-		return;
+		return NULL;
 	}
 	
@@ -211,42 +396,10 @@
 	 * Get driver name
 	 */
-	ipc_callid_t callid;
-	size_t name_size;
-	if (!async_data_write_receive(&callid, &name_size)) {
+	int rc = async_data_string_receive(&driver->name, DEVMAP_NAME_MAXLEN);
+	if (rc != EOK) {
 		free(driver);
-		ipc_answer_0(callid, EREFUSED);
-		ipc_answer_0(iid, EREFUSED);
-		return;
-	}
-	
-	if (name_size > DEVMAP_NAME_MAXLEN) {
-		free(driver);
-		ipc_answer_0(callid, EINVAL);
-		ipc_answer_0(iid, EREFUSED);
-		return;
-	}
-	
-	/*
-	 * Allocate buffer for device name.
-	 */
-	driver->name = (char *) malloc(name_size + 1);
-	if (driver->name == NULL) {
-		free(driver);
-		ipc_answer_0(callid, ENOMEM);
-		ipc_answer_0(iid, EREFUSED);
-		return;
-	}
-	
-	/*
-	 * Send confirmation to sender and get data into buffer.
-	 */
-	if (async_data_write_finalize(callid, driver->name, name_size) != EOK) {
-		free(driver->name);
-		free(driver);
-		ipc_answer_0(iid, EREFUSED);
-		return;
-	}
-	
-	driver->name[name_size] = 0;
+		ipc_answer_0(iid, rc);
+		return NULL;
+	}
 	
 	/* Initialize mutex for list of devices owned by this driver */
@@ -262,5 +415,5 @@
 	 */
 	ipc_call_t call;
-	callid = async_get_call(&call);
+	ipc_callid_t callid = async_get_call(&call);
 	
 	if (IPC_GET_METHOD(call) != IPC_M_CONNECT_TO_ME) {
@@ -270,5 +423,5 @@
 		free(driver);
 		ipc_answer_0(iid, ENOTSUP);
-		return;
+		return NULL;
 	}
 	
@@ -293,5 +446,5 @@
 	ipc_answer_0(iid, EOK);
 	
-	*odriver = driver;
+	return driver;
 }
 
@@ -355,42 +508,43 @@
 	}
 	
-	/* Get device name */
-	ipc_callid_t callid;
-	size_t size;
-	if (!async_data_write_receive(&callid, &size)) {
+	/* Get fqdn */
+	char *fqdn;
+	int rc = async_data_string_receive(&fqdn, DEVMAP_NAME_MAXLEN);
+	if (rc != EOK) {
 		free(device);
-		ipc_answer_0(iid, EREFUSED);
-		return;
-	}
-	
-	if (size > DEVMAP_NAME_MAXLEN) {
+		ipc_answer_0(iid, rc);
+		return;
+	}
+	
+	char *ns_name;
+	if (!devmap_fqdn_split(fqdn, &ns_name, &device->name)) {
+		free(fqdn);
 		free(device);
-		ipc_answer_0(callid, EINVAL);
-		ipc_answer_0(iid, EREFUSED);
-		return;
-	}
-	
-	/* +1 for terminating \0 */
-	device->name = (char *) malloc(size + 1);
-	
-	if (device->name == NULL) {
+		ipc_answer_0(iid, EINVAL);
+		return;
+	}
+	
+	free(fqdn);
+	
+	fibril_mutex_lock(&devices_list_mutex);
+	
+	devmap_namespace_t *namespace = devmap_namespace_create(ns_name);
+	free(ns_name);
+	if (!namespace) {
+		fibril_mutex_unlock(&devices_list_mutex);
 		free(device);
-		ipc_answer_0(callid, ENOMEM);
-		ipc_answer_0(iid, EREFUSED);
-		return;
-	}
-	
-	async_data_write_finalize(callid, device->name, size);
-	device->name[size] = 0;
+		ipc_answer_0(iid, ENOMEM);
+		return;
+	}
 	
 	list_initialize(&(device->devices));
 	list_initialize(&(device->driver_devices));
 	
-	fibril_mutex_lock(&devices_list_mutex);
-	
-	/* Check that device with such name is not already registered */
-	if (NULL != devmap_device_find_name(device->name)) {
-		printf(NAME ": Device '%s' already registered\n", device->name);
+	/* Check that device is not already registered */
+	if (devmap_device_find_name(namespace->name, device->name) != NULL) {
+		printf(NAME ": Device '%s/%s' already registered\n", device->namespace, device->name);
+		devmap_namespace_destroy(namespace);
 		fibril_mutex_unlock(&devices_list_mutex);
+		free(device->namespace);
 		free(device->name);
 		free(device);
@@ -402,4 +556,5 @@
 	device->handle = devmap_create_handle();
 	
+	devmap_namespace_addref(namespace, device);
 	device->driver = driver;
 	
@@ -437,4 +592,6 @@
 static void devmap_forward(ipc_callid_t callid, ipc_call_t *call)
 {
+	fibril_mutex_lock(&devices_list_mutex);
+	
 	/*
 	 * Get handle from request
@@ -450,4 +607,6 @@
 	ipc_forward_fast(callid, dev->driver->phone, dev->handle,
 	    IPC_GET_ARG3(*call), 0, IPC_FF_NONE);
+	
+	fibril_mutex_unlock(&devices_list_mutex);
 }
 
@@ -458,53 +617,34 @@
  *
  */
-static void devmap_get_handle(ipc_callid_t iid, ipc_call_t *icall)
-{
-	/*
-	 * Wait for incoming message with device name (but do not
-	 * read the name itself until the buffer is allocated).
-	 */
-	ipc_callid_t callid;
-	size_t size;
-	if (!async_data_write_receive(&callid, &size)) {
-		ipc_answer_0(callid, EREFUSED);
-		ipc_answer_0(iid, EREFUSED);
-		return;
-	}
-	
-	if ((size < 1) || (size > DEVMAP_NAME_MAXLEN)) {
-		ipc_answer_0(callid, EINVAL);
-		ipc_answer_0(iid, EREFUSED);
-		return;
-	}
-	
-	/*
-	 * Allocate buffer for device name.
-	 */
-	char *name = (char *) malloc(size + 1);
-	if (name == NULL) {
-		ipc_answer_0(callid, ENOMEM);
-		ipc_answer_0(iid, EREFUSED);
-		return;
-	}
-	
-	/*
-	 * Send confirmation to sender and get data into buffer.
-	 */
-	ipcarg_t retval = async_data_write_finalize(callid, name, size);
-	if (retval != EOK) {
-		ipc_answer_0(iid, EREFUSED);
-		free(name);
-		return;
-	}
-	name[size] = '\0';
+static void devmap_device_get_handle(ipc_callid_t iid, ipc_call_t *icall)
+{
+	char *fqdn;
+	
+	/* Get fqdn */
+	int rc = async_data_string_receive(&fqdn, DEVMAP_NAME_MAXLEN);
+	if (rc != EOK) {
+		ipc_answer_0(iid, rc);
+		return;
+	}
+	
+	char *ns_name;
+	char *name;
+	if (!devmap_fqdn_split(fqdn, &ns_name, &name)) {
+		free(fqdn);
+		ipc_answer_0(iid, EINVAL);
+		return;
+	}
+	
+	free(fqdn);
 	
 	fibril_mutex_lock(&devices_list_mutex);
 	const devmap_device_t *dev;
+	
 recheck:
-
+	
 	/*
 	 * Find device name in the list of known devices.
 	 */
-	dev = devmap_device_find_name(name);
+	dev = devmap_device_find_name(ns_name, name);
 	
 	/*
@@ -520,4 +660,5 @@
 		
 		ipc_answer_0(iid, ENOENT);
+		free(ns_name);
 		free(name);
 		fibril_mutex_unlock(&devices_list_mutex);
@@ -527,51 +668,96 @@
 	
 	ipc_answer_1(iid, EOK, dev->handle);
+	free(ns_name);
 	free(name);
 }
 
-/** Find name of device identified by id and send it to caller.
- *
- */
-static void devmap_get_name(ipc_callid_t iid, ipc_call_t *icall)
-{
-	const devmap_device_t *device = devmap_device_find_handle(IPC_GET_ARG1(*icall));
+/** Find handle for namespace identified by name.
+ *
+ * In answer will be send EOK and device handle in arg1 or a error
+ * code from errno.h.
+ *
+ */
+static void devmap_namespace_get_handle(ipc_callid_t iid, ipc_call_t *icall)
+{
+	char *name;
+	
+	/* Get device name */
+	int rc = async_data_string_receive(&name, DEVMAP_NAME_MAXLEN);
+	if (rc != EOK) {
+		ipc_answer_0(iid, rc);
+		return;
+	}
+	
+	fibril_mutex_lock(&devices_list_mutex);
+	const devmap_namespace_t *namespace;
+	
+recheck:
 	
 	/*
-	 * Device not found.
+	 * Find namespace name in the list of known namespaces.
 	 */
-	if (device == NULL) {
+	namespace = devmap_namespace_find_name(name);
+	
+	/*
+	 * Namespace was not found.
+	 */
+	if (namespace == NULL) {
+		if (IPC_GET_ARG1(*icall) & IPC_FLAG_BLOCKING) {
+			/* Blocking lookup */
+			fibril_condvar_wait(&devices_list_cv,
+			    &devices_list_mutex);
+			goto recheck;
+		}
+		
 		ipc_answer_0(iid, ENOENT);
-		return;
-	}
-	
-	ipc_answer_0(iid, EOK);
-	
-	/* FIXME:
-	 * We have no channel from DEVMAP to client, therefore
-	 * sending must be initiated by client.
-	 *
-	 * size_t name_size = str_size(device->name);
-	 *
-	 * int rc = async_data_write_send(phone, device->name, name_size);
-	 * if (rc != EOK) {
-	 *     async_wait_for(req, NULL);
-	 *     return rc;
-	 * }
-	 */
-	
-	/* TODO: send name in response */
-}
-
-static void devmap_get_count(ipc_callid_t iid, ipc_call_t *icall)
+		free(name);
+		fibril_mutex_unlock(&devices_list_mutex);
+		return;
+	}
+	fibril_mutex_unlock(&devices_list_mutex);
+	
+	ipc_answer_1(iid, EOK, namespace->handle);
+	free(name);
+}
+
+static void devmap_handle_probe(ipc_callid_t iid, ipc_call_t *icall)
 {
 	fibril_mutex_lock(&devices_list_mutex);
-	ipc_answer_1(iid, EOK, list_count(&devices_list));
+	
+	devmap_namespace_t *namespace = devmap_namespace_find_handle(IPC_GET_ARG1(*icall));
+	if (namespace == NULL) {
+		devmap_device_t *dev = devmap_device_find_handle(IPC_GET_ARG1(*icall));
+		if (dev == NULL)
+			ipc_answer_1(iid, EOK, DEV_HANDLE_NONE);
+		else
+			ipc_answer_1(iid, EOK, DEV_HANDLE_DEVICE);
+	} else
+		ipc_answer_1(iid, EOK, DEV_HANDLE_NAMESPACE);
+	
 	fibril_mutex_unlock(&devices_list_mutex);
 }
 
-static void devmap_get_devices(ipc_callid_t iid, ipc_call_t *icall)
+static void devmap_get_namespace_count(ipc_callid_t iid, ipc_call_t *icall)
 {
 	fibril_mutex_lock(&devices_list_mutex);
-	
+	ipc_answer_1(iid, EOK, list_count(&namespaces_list));
+	fibril_mutex_unlock(&devices_list_mutex);
+}
+
+static void devmap_get_device_count(ipc_callid_t iid, ipc_call_t *icall)
+{
+	fibril_mutex_lock(&devices_list_mutex);
+	
+	devmap_namespace_t *namespace = devmap_namespace_find_handle(IPC_GET_ARG1(*icall));
+	if (namespace == NULL)
+		ipc_answer_0(iid, EEXISTS);
+	else
+		ipc_answer_1(iid, EOK, namespace->refcnt);
+	
+	fibril_mutex_unlock(&devices_list_mutex);
+}
+
+static void devmap_get_namespaces(ipc_callid_t iid, ipc_call_t *icall)
+{
 	ipc_callid_t callid;
 	size_t size;
@@ -584,9 +770,80 @@
 	if ((size % sizeof(dev_desc_t)) != 0) {
 		ipc_answer_0(callid, EINVAL);
+		ipc_answer_0(iid, EINVAL);
+		return;
+	}
+	
+	fibril_mutex_lock(&devices_list_mutex);
+	
+	size_t count = size / sizeof(dev_desc_t);
+	if (count != list_count(&namespaces_list)) {
+		ipc_answer_0(callid, EOVERFLOW);
+		ipc_answer_0(iid, EOVERFLOW);
+		return;
+	}
+	
+	dev_desc_t *desc = (dev_desc_t *) malloc(size);
+	if (desc == NULL) {
+		ipc_answer_0(callid, ENOMEM);
+		ipc_answer_0(iid, ENOMEM);
+		return;
+	}
+	
+	link_t *item = namespaces_list.next;
+	size_t pos = 0;
+	while (item != &namespaces_list) {
+		devmap_namespace_t *namespace = list_get_instance(item, devmap_namespace_t, namespaces);
+		
+		desc[pos].handle = namespace->handle;
+		str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, namespace->name);
+		pos++;
+		
+		item = item->next;
+	}
+	
+	ipcarg_t retval = async_data_read_finalize(callid, desc, size);
+	
+	free(desc);
+	fibril_mutex_unlock(&devices_list_mutex);
+	
+	ipc_answer_0(iid, retval);
+}
+
+static void devmap_get_devices(ipc_callid_t iid, ipc_call_t *icall)
+{
+	/* FIXME: Use faster algorithm which can make better use
+	   of namespaces */
+	
+	ipc_callid_t callid;
+	size_t size;
+	if (!async_data_read_receive(&callid, &size)) {
+		ipc_answer_0(callid, EREFUSED);
 		ipc_answer_0(iid, EREFUSED);
 		return;
 	}
 	
+	if ((size % sizeof(dev_desc_t)) != 0) {
+		ipc_answer_0(callid, EINVAL);
+		ipc_answer_0(iid, EINVAL);
+		return;
+	}
+	
+	fibril_mutex_lock(&devices_list_mutex);
+	
+	devmap_namespace_t *namespace = devmap_namespace_find_handle(IPC_GET_ARG1(*icall));
+	if (namespace == NULL) {
+		fibril_mutex_unlock(&devices_list_mutex);
+		ipc_answer_0(callid, ENOENT);
+		ipc_answer_0(iid, ENOENT);
+		return;
+	}
+	
 	size_t count = size / sizeof(dev_desc_t);
+	if (count != namespace->refcnt) {
+		ipc_answer_0(callid, EOVERFLOW);
+		ipc_answer_0(iid, EOVERFLOW);
+		return;
+	}
+	
 	dev_desc_t *desc = (dev_desc_t *) malloc(size);
 	if (desc == NULL) {
@@ -596,28 +853,24 @@
 	}
 	
+	link_t *item = devices_list.next;
 	size_t pos = 0;
-	link_t *item = devices_list.next;
-	
-	while ((item != &devices_list) && (pos < count)) {
+	while (item != &devices_list) {
 		devmap_device_t *device = list_get_instance(item, devmap_device_t, devices);
 		
-		desc[pos].handle = device->handle;
-		str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, device->name);
-		pos++;
+		if (device->namespace == namespace) {
+			desc[pos].handle = device->handle;
+			str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, device->name);
+			pos++;
+		}
+		
 		item = item->next;
 	}
 	
-	ipcarg_t retval = async_data_read_finalize(callid, desc, pos * sizeof(dev_desc_t));
-	if (retval != EOK) {
-		ipc_answer_0(iid, EREFUSED);
-		free(desc);
-		return;
-	}
+	ipcarg_t retval = async_data_read_finalize(callid, desc, size);
 	
 	free(desc);
-	
 	fibril_mutex_unlock(&devices_list_mutex);
 	
-	ipc_answer_1(iid, EOK, pos);
+	ipc_answer_0(iid, retval);
 }
 
@@ -642,5 +895,14 @@
 	}
 	
-	/* Create NULL device entry */
+	char null[DEVMAP_NAME_MAXLEN];
+	snprintf(null, DEVMAP_NAME_MAXLEN, "%u", i);
+	
+	char *dev_name = str_dup(null);
+	if (dev_name == NULL) {
+		fibril_mutex_unlock(&null_devices_mutex);
+		ipc_answer_0(iid, ENOMEM);
+		return;
+	}
+	
 	devmap_device_t *device = (devmap_device_t *) malloc(sizeof(devmap_device_t));
 	if (device == NULL) {
@@ -650,11 +912,10 @@
 	}
 	
-	char null[DEVMAP_NAME_MAXLEN];
-	snprintf(null, DEVMAP_NAME_MAXLEN, "null%u", i);
-	
-	device->name = str_dup(null);
-	if (device->name == NULL) {
+	fibril_mutex_lock(&devices_list_mutex);
+	
+	devmap_namespace_t *namespace = devmap_namespace_create("null");
+	if (!namespace) {
+		fibril_mutex_lock(&devices_list_mutex);
 		fibril_mutex_unlock(&null_devices_mutex);
-		free(device);
 		ipc_answer_0(iid, ENOMEM);
 		return;
@@ -663,10 +924,11 @@
 	list_initialize(&(device->devices));
 	list_initialize(&(device->driver_devices));
-	
-	fibril_mutex_lock(&devices_list_mutex);
 	
 	/* Get unique device handle */
 	device->handle = devmap_create_handle();
 	device->driver = NULL;
+	
+	devmap_namespace_addref(namespace, device);
+	device->name = dev_name;
 	
 	/* Insert device into list of all devices
@@ -692,5 +954,8 @@
 	}
 	
+	fibril_mutex_lock(&devices_list_mutex);
 	devmap_device_unregister_core(null_devices[i]);
+	fibril_mutex_unlock(&devices_list_mutex);
+	
 	null_devices[i] = NULL;
 	
@@ -725,8 +990,6 @@
 	ipc_answer_0(iid, EOK);
 	
-	devmap_driver_t *driver = NULL;
-	devmap_driver_register(&driver);
-	
-	if (NULL == driver)
+	devmap_driver_t *driver = devmap_driver_register();
+	if (driver == NULL)
 		return;
 	
@@ -755,8 +1018,8 @@
 			break;
 		case DEVMAP_DEVICE_GET_HANDLE:
-			devmap_get_handle(callid, &call);
-			break;
-		case DEVMAP_DEVICE_GET_NAME:
-			devmap_get_name(callid, &call);
+			devmap_device_get_handle(callid, &call);
+			break;
+		case DEVMAP_NAMESPACE_GET_HANDLE:
+			devmap_namespace_get_handle(callid, &call);
 			break;
 		default:
@@ -793,19 +1056,28 @@
 			continue;
 		case DEVMAP_DEVICE_GET_HANDLE:
-			devmap_get_handle(callid, &call);
-			break;
-		case DEVMAP_DEVICE_GET_NAME:
-			devmap_get_name(callid, &call);
-			break;
-		case DEVMAP_DEVICE_NULL_CREATE:
+			devmap_device_get_handle(callid, &call);
+			break;
+		case DEVMAP_NAMESPACE_GET_HANDLE:
+			devmap_namespace_get_handle(callid, &call);
+			break;
+		case DEVMAP_HANDLE_PROBE:
+			devmap_handle_probe(callid, &call);
+			break;
+		case DEVMAP_NULL_CREATE:
 			devmap_null_create(callid, &call);
 			break;
-		case DEVMAP_DEVICE_NULL_DESTROY:
+		case DEVMAP_NULL_DESTROY:
 			devmap_null_destroy(callid, &call);
 			break;
-		case DEVMAP_DEVICE_GET_COUNT:
-			devmap_get_count(callid, &call);
-			break;
-		case DEVMAP_DEVICE_GET_DEVICES:
+		case DEVMAP_GET_NAMESPACE_COUNT:
+			devmap_get_namespace_count(callid, &call);
+			break;
+		case DEVMAP_GET_DEVICE_COUNT:
+			devmap_get_device_count(callid, &call);
+			break;
+		case DEVMAP_GET_NAMESPACES:
+			devmap_get_namespaces(callid, &call);
+			break;
+		case DEVMAP_GET_DEVICES:
 			devmap_get_devices(callid, &call);
 			break;
