Index: uspace/srv/bd/gxe_bd/gxe_bd.c
===================================================================
--- uspace/srv/bd/gxe_bd/gxe_bd.c	(revision faba83975da4ba5bb605f70d4e02e065f9513e84)
+++ uspace/srv/bd/gxe_bd/gxe_bd.c	(revision cddcc4a3904768c1032861a518e712bd08ea3156)
@@ -39,7 +39,7 @@
 #include <libarch/ddi.h>
 #include <ddi.h>
-#include <ipc/bd.h>
 #include <async.h>
 #include <as.h>
+#include <bd_srv.h>
 #include <fibril_synch.h>
 #include <loc.h>
@@ -65,4 +65,5 @@
 };
 
+/** GXE disk hardware registers */
 typedef struct {
 	uint32_t offset_lo;
@@ -83,25 +84,49 @@
 
 	uint8_t buffer[512];
+} gxe_bd_hw_t;
+
+/** GXE block device soft state */
+typedef struct {
+	/** Block device server structure */
+	bd_srv_t bd;
+	int disk_id;
 } gxe_bd_t;
 
-
 static const size_t block_size = 512;
-static size_t comm_size;
 
 static uintptr_t dev_physical = 0x13000000;
-static gxe_bd_t *dev;
+static gxe_bd_hw_t *dev;
 
 static service_id_t service_id[MAX_DISKS];
 
 static fibril_mutex_t dev_lock[MAX_DISKS];
+
+static gxe_bd_t gxe_bd[MAX_DISKS];
 
 static int gxe_bd_init(void);
 static void gxe_bd_connection(ipc_callid_t iid, ipc_call_t *icall, void *);
-static int gxe_bd_read_blocks(int disk_id, uint64_t ba, unsigned cnt,
-    void *buf);
-static int gxe_bd_write_blocks(int disk_id, uint64_t ba, unsigned cnt,
-    const void *buf);
 static int gxe_bd_read_block(int disk_id, uint64_t ba, void *buf);
 static int gxe_bd_write_block(int disk_id, uint64_t ba, const void *buf);
+
+static int gxe_bd_open(bd_srv_t *);
+static int gxe_bd_close(bd_srv_t *);
+static int gxe_bd_read_blocks(bd_srv_t *, aoff64_t, size_t, void *, size_t);
+static int gxe_bd_write_blocks(bd_srv_t *, aoff64_t, size_t, const void *, size_t);
+static int gxe_bd_get_block_size(bd_srv_t *, size_t *);
+static int gxe_bd_get_num_blocks(bd_srv_t *, aoff64_t *);
+
+static bd_ops_t gxe_bd_ops = {
+	.open = gxe_bd_open,
+	.close = gxe_bd_close,
+	.read_blocks = gxe_bd_read_blocks,
+	.write_blocks = gxe_bd_write_blocks,
+	.get_block_size = gxe_bd_get_block_size,
+	.get_num_blocks = gxe_bd_get_num_blocks
+};
+
+static gxe_bd_t *bd_srv_gxe(bd_srv_t *bd)
+{
+	return (gxe_bd_t *)bd->arg;
+}
 
 int main(int argc, char **argv)
@@ -130,5 +155,5 @@
 	
 	void *vaddr;
-	rc = pio_enable((void *) dev_physical, sizeof(gxe_bd_t), &vaddr);
+	rc = pio_enable((void *) dev_physical, sizeof(gxe_bd_hw_t), &vaddr);
 	if (rc != EOK) {
 		printf("%s: Could not initialize device I/O space.\n", NAME);
@@ -140,4 +165,8 @@
 	for (unsigned int i = 0; i < MAX_DISKS; i++) {
 		char name[16];
+		
+		bd_srv_init(&gxe_bd[i].bd);
+		gxe_bd[i].bd.ops = &gxe_bd_ops;
+		gxe_bd[i].bd.arg = (void *)&gxe_bd[i];
 		
 		snprintf(name, 16, "%s/disk%u", NAMESPACE, i);
@@ -157,13 +186,5 @@
 static void gxe_bd_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
 {
-	void *fs_va = NULL;
-	ipc_callid_t callid;
-	ipc_call_t call;
-	sysarg_t method;
 	service_id_t dsid;
-	unsigned int flags;
-	int retval;
-	uint64_t ba;
-	unsigned cnt;
 	int disk_id, i;
 
@@ -182,73 +203,28 @@
 	}
 
-	/* Answer the IPC_M_CONNECT_ME_TO call. */
-	async_answer_0(iid, EOK);
-
-	if (!async_share_out_receive(&callid, &comm_size, &flags)) {
-		async_answer_0(callid, EHANGUP);
-		return;
-	}
-
-	if (comm_size < block_size) {
-		async_answer_0(callid, EHANGUP);
-		return;
-	}
-
-	(void) async_share_out_finalize(callid, &fs_va);
-	if (fs_va == AS_MAP_FAILED) {
-		async_answer_0(callid, EHANGUP);
-		return;
-	}
-
-	while (true) {
-		callid = async_get_call(&call);
-		method = IPC_GET_IMETHOD(call);
-		
-		if (!method) {
-			/* The other side has hung up. */
-			async_answer_0(callid, EOK);
-			return;
-		}
-		
-		switch (method) {
-		case BD_READ_BLOCKS:
-			ba = MERGE_LOUP32(IPC_GET_ARG1(call),
-			    IPC_GET_ARG2(call));
-			cnt = IPC_GET_ARG3(call);
-			if (cnt * block_size > comm_size) {
-				retval = ELIMIT;
-				break;
-			}
-			retval = gxe_bd_read_blocks(disk_id, ba, cnt, fs_va);
-			break;
-		case BD_WRITE_BLOCKS:
-			ba = MERGE_LOUP32(IPC_GET_ARG1(call),
-			    IPC_GET_ARG2(call));
-			cnt = IPC_GET_ARG3(call);
-			if (cnt * block_size > comm_size) {
-				retval = ELIMIT;
-				break;
-			}
-			retval = gxe_bd_write_blocks(disk_id, ba, cnt, fs_va);
-			break;
-		case BD_GET_BLOCK_SIZE:
-			async_answer_1(callid, EOK, block_size);
-			continue;
-		case BD_GET_NUM_BLOCKS:
-			retval = ENOTSUP;
-			break;
-		default:
-			retval = EINVAL;
-			break;
-		}
-		async_answer_0(callid, retval);
-	}
+	bd_conn(iid, icall, &gxe_bd[disk_id].bd);
+}
+
+/** Open device. */
+static int gxe_bd_open(bd_srv_t *bd)
+{
+	return EOK;
+}
+
+/** Close device. */
+static int gxe_bd_close(bd_srv_t *bd)
+{
+	return EOK;
 }
 
 /** Read multiple blocks from the device. */
-static int gxe_bd_read_blocks(int disk_id, uint64_t ba, unsigned cnt,
-    void *buf) {
-
+static int gxe_bd_read_blocks(bd_srv_t *bd, aoff64_t ba, size_t cnt,
+    void *buf, size_t size)
+{
+	int disk_id = bd_srv_gxe(bd)->disk_id;
 	int rc;
+
+	if (size < cnt * block_size)
+		return EINVAL;
 
 	while (cnt > 0) {
@@ -266,8 +242,12 @@
 
 /** Write multiple blocks to the device. */
-static int gxe_bd_write_blocks(int disk_id, uint64_t ba, unsigned cnt,
-    const void *buf) {
-
+static int gxe_bd_write_blocks(bd_srv_t *bd, aoff64_t ba, size_t cnt,
+    const void *buf, size_t size)
+{
+	int disk_id = bd_srv_gxe(bd)->disk_id;
 	int rc;
+
+	if (size < cnt * block_size)
+		return EINVAL;
 
 	while (cnt > 0) {
@@ -282,4 +262,17 @@
 
 	return EOK;
+}
+
+/** Get device block size. */
+static int gxe_bd_get_block_size(bd_srv_t *bd, size_t *rsize)
+{
+	*rsize = block_size;
+	return EOK;
+}
+
+/** Get number of blocks on device. */
+static int gxe_bd_get_num_blocks(bd_srv_t *bd, aoff64_t *rnb)
+{
+	return ENOTSUP;
 }
 
