Index: uspace/srv/devman/main.c
===================================================================
--- uspace/srv/devman/main.c	(revision 7beb220448680668678a63d26f84dedb2b14be05)
+++ uspace/srv/devman/main.c	(revision 422722e64b724fdbff99b610f05f336291dc1b6b)
@@ -65,25 +65,18 @@
 static dev_tree_t device_tree;
 
+static int init_running_drv(void *drv);
+
 /** Register running driver. */
-static driver_t *devman_driver_register(void)
-{
-	ipc_call_t icall;
-	ipc_callid_t iid;
+static driver_t *devman_driver_register(ipc_callid_t callid, ipc_call_t *call)
+{
 	driver_t *driver = NULL;
+	char *drv_name = NULL;
 
 	log_msg(LVL_DEBUG, "devman_driver_register");
-	
-	iid = async_get_call(&icall);
-	if (IPC_GET_IMETHOD(icall) != DEVMAN_DRIVER_REGISTER) {
-		async_answer_0(iid, EREFUSED);
-		return NULL;
-	}
-	
-	char *drv_name = NULL;
 	
 	/* Get driver name. */
 	int rc = async_data_write_accept((void **) &drv_name, true, 0, 0, 0, 0);
 	if (rc != EOK) {
-		async_answer_0(iid, rc);
+		async_answer_0(callid, rc);
 		return NULL;
 	}
@@ -98,5 +91,5 @@
 		free(drv_name);
 		drv_name = NULL;
-		async_answer_0(iid, ENOENT);
+		async_answer_0(callid, ENOENT);
 		return NULL;
 	}
@@ -112,5 +105,5 @@
 		    driver->name);
 		fibril_mutex_unlock(&driver->driver_mutex);
-		async_answer_0(iid, EEXISTS);
+		async_answer_0(callid, EEXISTS);
 		return NULL;
 	}
@@ -134,12 +127,12 @@
 	log_msg(LVL_DEBUG, "Creating connection to the `%s' driver.",
 	    driver->name);
-	driver->sess = async_callback_receive(EXCHANGE_SERIALIZE);
+	driver->sess = async_callback_receive(EXCHANGE_PARALLEL);
 	if (!driver->sess) {
 		fibril_mutex_unlock(&driver->driver_mutex);
-		async_answer_0(iid, ENOTSUP);
+		async_answer_0(callid, ENOTSUP);
 		return NULL;
 	}
-	
-	fibril_mutex_unlock(&driver->driver_mutex);
+	/* FIXME: Work around problem with callback sessions */
+	async_sess_args_set(driver->sess, DRIVER_DEVMAN, 0, 0);
 	
 	log_msg(LVL_NOTE,
@@ -147,6 +140,22 @@
 	    driver->name);
 	
-	async_answer_0(iid, EOK);
-	
+	/*
+	 * Initialize the driver as running (e.g. pass assigned devices to it)
+	 * in a separate fibril; the separate fibril is used to enable the
+	 * driver to use devman service during the driver's initialization.
+	 */
+	fid_t fid = fibril_create(init_running_drv, driver);
+	if (fid == 0) {
+		log_msg(LVL_ERROR, "Failed to create initialization fibril " \
+		    "for driver `%s'.", driver->name);
+		fibril_mutex_unlock(&driver->driver_mutex);
+		async_answer_0(callid, ENOMEM);
+		return NULL;
+	}
+	
+	fibril_add_ready(fid);
+	fibril_mutex_unlock(&driver->driver_mutex);
+	
+	async_answer_0(callid, EOK);
 	return driver;
 }
@@ -429,23 +438,15 @@
 static void devman_connection_driver(ipc_callid_t iid, ipc_call_t *icall)
 {
+	client_t *client;
+	driver_t *driver;
+	
 	/* Accept the connection. */
 	async_answer_0(iid, EOK);
 	
-	driver_t *driver = devman_driver_register();
-	if (driver == NULL)
-		return;
-	
-	/*
-	 * Initialize the driver as running (e.g. pass assigned devices to it)
-	 * in a separate fibril; the separate fibril is used to enable the
-	 * driver to use devman service during the driver's initialization.
-	 */
-	fid_t fid = fibril_create(init_running_drv, driver);
-	if (fid == 0) {
-		log_msg(LVL_ERROR, "Failed to create initialization fibril " \
-		    "for driver `%s'.", driver->name);
-		return;
-	}
-	fibril_add_ready(fid);
+	client = async_get_client_data();
+	if (client == NULL) {
+		log_msg(LVL_ERROR, "Failed to allocate client data.");
+		return;
+	}
 	
 	while (true) {
@@ -456,5 +457,26 @@
 			break;
 		
+		if (IPC_GET_IMETHOD(call) != DEVMAN_DRIVER_REGISTER) {
+			fibril_mutex_lock(&client->mutex);
+			driver = client->driver;
+			fibril_mutex_unlock(&client->mutex);
+			if (driver == NULL) {
+				/* First call must be to DEVMAN_DRIVER_REGISTER */
+				async_answer_0(callid, ENOTSUP);
+				continue;
+			}
+		}
+		
 		switch (IPC_GET_IMETHOD(call)) {
+		case DEVMAN_DRIVER_REGISTER:
+			fibril_mutex_lock(&client->mutex);
+			if (client->driver != NULL) {
+				fibril_mutex_unlock(&client->mutex);
+				async_answer_0(callid, EINVAL);
+				continue;
+			}
+			client->driver = devman_driver_register(callid, &call);
+			fibril_mutex_unlock(&client->mutex);
+			break;
 		case DEVMAN_ADD_FUNCTION:
 			devman_add_function(callid, &call);
@@ -814,5 +836,5 @@
 static void devman_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
-	/* Select interface. */
+	/* Select port. */
 	switch ((sysarg_t) (IPC_GET_ARG1(*icall))) {
 	case DEVMAN_DRIVER:
@@ -840,4 +862,21 @@
 }
 
+static void *devman_client_data_create(void)
+{
+	client_t *client;
+	
+	client = calloc(1, sizeof(client_t));
+	if (client == NULL)
+		return NULL;
+	
+	fibril_mutex_initialize(&client->mutex);
+	return client;
+}
+
+static void devman_client_data_destroy(void *data)
+{
+	free(data);
+}
+
 /** Initialize device manager internal structures. */
 static bool devman_init(void)
@@ -886,5 +925,7 @@
 	}
 	
-	/* Set a handler of incomming connections. */
+	/* Set handlers for incoming connections. */
+	async_set_client_data_constructor(devman_client_data_create);
+	async_set_client_data_destructor(devman_client_data_destroy);
 	async_set_client_connection(devman_connection);
 
