Index: uspace/lib/libblock/libblock.c
===================================================================
--- uspace/lib/libblock/libblock.c	(revision 7858bc5ff895eb1e87b5c19c5e2ca2a23717133a)
+++ uspace/lib/libblock/libblock.c	(revision 916bf1adc0fc4678d0a3a3b704a428ccc4e2c303)
@@ -47,9 +47,78 @@
 #include <as.h>
 #include <assert.h>
-
-static int dev_phone = -1;		/* FIXME */
-static void *dev_buffer = NULL;		/* FIXME */
-static size_t dev_buffer_len = 0;	/* FIXME */
-static void *bblock = NULL;		/* FIXME */
+#include <futex.h>
+#include <libadt/list.h>
+
+/** Lock protecting the device connection list */
+static futex_t dcl_lock = FUTEX_INITIALIZER;
+/** Device connection list head. */
+static LIST_INITIALIZE(dcl_head);
+
+typedef struct {
+	link_t link;
+	int dev_handle;
+	int dev_phone;
+	void *com_area;
+	size_t com_size;
+	void *bb_buf;
+	off_t bb_off;
+	size_t bb_size;
+} devcon_t;
+
+static devcon_t *devcon_search(dev_handle_t dev_handle)
+{
+	link_t *cur;
+
+	futex_down(&dcl_lock);
+	for (cur = dcl_head.next; cur != &dcl_head; cur = cur->next) {
+		devcon_t *devcon = list_get_instance(cur, devcon_t, link);
+		if (devcon->dev_handle == dev_handle) {
+			futex_up(&dcl_lock);
+			return devcon;
+		}
+	}
+	futex_up(&dcl_lock);
+	return NULL;
+}
+
+static int devcon_add(dev_handle_t dev_handle, int dev_phone, void *com_area,
+   size_t com_size, void *bb_buf, off_t bb_off, size_t bb_size)
+{
+	link_t *cur;
+	devcon_t *devcon;
+
+	devcon = malloc(sizeof(devcon_t));
+	if (!devcon)
+		return ENOMEM;
+	
+	link_initialize(&devcon->link);
+	devcon->dev_handle = dev_handle;
+	devcon->dev_phone = dev_phone;
+	devcon->com_area = com_area;
+	devcon->com_size = com_size;
+	devcon->bb_buf = bb_buf;
+	devcon->bb_off = bb_off;
+	devcon->bb_size = bb_size;
+
+	futex_down(&dcl_lock);
+	for (cur = dcl_head.next; cur != &dcl_head; cur = cur->next) {
+		devcon_t *d = list_get_instance(cur, devcon_t, link);
+		if (d->dev_handle == dev_handle) {
+			futex_up(&dcl_lock);
+			free(devcon);
+			return EEXIST;
+		}
+	}
+	list_append(&devcon->link, &dcl_head);
+	futex_up(&dcl_lock);
+	return EOK;
+}
+
+static void devcon_remove(devcon_t *devcon)
+{
+	futex_down(&dcl_lock);
+	list_remove(&devcon->link);
+	futex_up(&dcl_lock);
+}
 
 int
@@ -58,13 +127,16 @@
 {
 	int rc;
-
-	bblock = malloc(bb_size);
-	if (!bblock)
+	int dev_phone;
+	void *com_area;
+	void *bb_buf;
+	
+	bb_buf = malloc(bb_size);
+	if (!bb_buf)
 		return ENOMEM;
-	dev_buffer_len = com_size;
-	dev_buffer = mmap(NULL, com_size, PROTO_READ | PROTO_WRITE,
+	
+	com_area = mmap(NULL, com_size, PROTO_READ | PROTO_WRITE,
 	    MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
-	if (!dev_buffer) {
-		free(bblock);
+	if (!com_area) {
+		free(bb_buf);
 		return ENOMEM;
 	}
@@ -73,26 +145,35 @@
 
 	if (dev_phone < 0) {
-		free(bblock);
-		munmap(dev_buffer, com_size);
+		free(bb_buf);
+		munmap(com_area, com_size);
 		return dev_phone;
 	}
 
-	rc = ipc_share_out_start(dev_phone, dev_buffer,
+	rc = ipc_share_out_start(dev_phone, com_area,
 	    AS_AREA_READ | AS_AREA_WRITE);
 	if (rc != EOK) {
+		free(bb_buf);
+	    	munmap(com_area, com_size);
 		ipc_hangup(dev_phone);
-		free(bblock);
-	    	munmap(dev_buffer, com_size);
 		return rc;
 	}
+	
+	rc = devcon_add(dev_handle, dev_phone, com_area, com_size, bb_buf,
+	    bb_off, bb_size);
+	if (rc != EOK) {
+		free(bb_buf);
+		munmap(com_area, com_size);
+		ipc_hangup(dev_phone);
+		return rc;
+	}
+
 	off_t bufpos = 0;
 	size_t buflen = 0;
 	if (!block_read(dev_handle, &bufpos, &buflen, &bb_off,
-	    bblock, bb_size, bb_size)) {
-	    	ipc_hangup(dev_phone);
-	    	free(bblock);
-		munmap(dev_buffer, com_size);
+	    bb_buf, bb_size, bb_size)) {
+		block_fini(dev_handle);
 		return EIO;	/* XXX real error code */
 	}
+	
 	return EOK;
 }
@@ -100,14 +181,21 @@
 void block_fini(dev_handle_t dev_handle)
 {
-	/* XXX */
-	free(bblock);
-	munmap(dev_buffer, dev_buffer_len);
-	ipc_hangup(dev_phone);
+	devcon_t *devcon = devcon_search(dev_handle);
+	assert(devcon);
+	
+	devcon_remove(devcon);
+
+	free(devcon->bb_buf);
+	munmap(devcon->com_area, devcon->com_size);
+	ipc_hangup(devcon->dev_phone);
+
+	free(devcon);	
 }
 
 void *block_bb_get(dev_handle_t dev_handle)
 {
-	/* XXX */
-	return bblock;
+	devcon_t *devcon = devcon_search(dev_handle);
+	assert(devcon);
+	return devcon->bb_buf;
 }
 
@@ -132,4 +220,6 @@
 	off_t offset = 0;
 	size_t left = size;
+	devcon_t *devcon = devcon_search(dev_handle);
+	assert(devcon);
 	
 	while (left > 0) {
@@ -146,5 +236,5 @@
 			 * destination buffer.
 			 */
-			memcpy(dst + offset, dev_buffer + *bufpos, rd);
+			memcpy(dst + offset, devcon->com_area + *bufpos, rd);
 			offset += rd;
 			*bufpos += rd;
@@ -156,5 +246,5 @@
 			/* Refill the communication buffer with a new block. */
 			ipcarg_t retval;
-			int rc = async_req_2_1(dev_phone, RD_READ_BLOCK,
+			int rc = async_req_2_1(devcon->dev_phone, RD_READ_BLOCK,
 			    *pos / block_size, block_size, &retval);
 			if ((rc != EOK) || (retval != EOK))
@@ -177,7 +267,4 @@
 	off_t pos = offset * bs;
 
-	assert(dev_phone != -1);
-	assert(dev_buffer);
-
 	b = malloc(sizeof(block_t));
 	if (!b)
