Index: uspace/drv/bus/usb/usbmast/main.c
===================================================================
--- uspace/drv/bus/usb/usbmast/main.c	(revision e6b32a8bd052699b36d163edb8ab9a99071ac6fc)
+++ uspace/drv/bus/usb/usbmast/main.c	(revision c936c7f9ded988d13c3729f1394182797ffa8d7e)
@@ -78,4 +78,5 @@
 };
 
+static int usbmast_fun_create(usbmast_dev_t *mdev, unsigned lun);
 static void usbmast_bd_connection(ipc_callid_t iid, ipc_call_t *icall,
     void *arg);
@@ -89,11 +90,10 @@
 {
 	int rc;
-	const char *fun_name = "a";
-	ddf_fun_t *fun = NULL;
-	usbmast_fun_t *msfun = NULL;
+	usbmast_dev_t *mdev = NULL;
+	unsigned i;
 
 	/* Allocate softstate */
-	msfun = calloc(1, sizeof(usbmast_fun_t));
-	if (msfun == NULL) {
+	mdev = calloc(1, sizeof(usbmast_dev_t));
+	if (mdev == NULL) {
 		usb_log_error("Failed allocating softstate.\n");
 		rc = ENOMEM;
@@ -101,17 +101,6 @@
 	}
 
-	msfun->usb_dev = dev;
-	msfun->lun = 0;
-
-	fun = ddf_fun_create(dev->ddf_dev, fun_exposed, fun_name);
-	if (fun == NULL) {
-		usb_log_error("Failed to create DDF function %s.\n", fun_name);
-		rc = ENOMEM;
-		goto error;
-	}
-
-	/* Set up a connection handler. */
-	fun->conn_handler = usbmast_bd_connection;
-	fun->driver_data = msfun;
+	mdev->ddf_dev = dev->ddf_dev;
+	mdev->usb_dev = dev;
 
 	usb_log_info("Initializing mass storage `%s'.\n",
@@ -125,38 +114,92 @@
 
 	usb_log_debug("Get LUN count...\n");
-	size_t lun_count = usb_masstor_get_lun_count(msfun);
-
-	/* XXX Handle more than one LUN properly. */
-	if (lun_count > 1) {
-		usb_log_warning ("Mass storage has %zu LUNs. Ignoring all "
-		    "but first.\n", lun_count);
-	}
+	mdev->luns = usb_masstor_get_lun_count(mdev);
+
+	for (i = 0; i < mdev->luns; i++) {
+		rc = usbmast_fun_create(mdev, i);
+		if (rc != EOK)
+			goto error;
+	}
+
+	return EOK;
+error:
+	/* XXX Destroy functions */
+	if (mdev != NULL)
+		free(mdev);
+	return rc;
+}
+
+/** Create mass storage function.
+ *
+ * Called once for each LUN.
+ *
+ * @param mdev		Mass storage device
+ * @param lun		LUN
+ * @return		EOK on success or negative error code.
+ */
+static int usbmast_fun_create(usbmast_dev_t *mdev, unsigned lun)
+{
+	int rc;
+	char *fun_name = NULL;
+	ddf_fun_t *fun = NULL;
+	usbmast_fun_t *mfun = NULL;
+
+	/* Allocate softstate */
+	mfun = calloc(1, sizeof(usbmast_fun_t));
+	if (mfun == NULL) {
+		usb_log_error("Failed allocating softstate.\n");
+		rc = ENOMEM;
+		goto error;
+	}
+
+	mfun->mdev = mdev;
+	mfun->lun = lun;
+
+	if (asprintf(&fun_name, "l%u", lun) < 0) {
+		usb_log_error("Out of memory.\n");
+		rc = ENOMEM;
+		goto error;
+	}
+
+	fun = ddf_fun_create(mdev->ddf_dev, fun_exposed, fun_name);
+	if (fun == NULL) {
+		usb_log_error("Failed to create DDF function %s.\n", fun_name);
+		rc = ENOMEM;
+		goto error;
+	}
+
+	free(fun_name);
+	fun_name = NULL;
+
+	/* Set up a connection handler. */
+	fun->conn_handler = usbmast_bd_connection;
+	fun->driver_data = mfun;
 
 	usb_log_debug("Inquire...\n");
 	usbmast_inquiry_data_t inquiry;
-	rc = usbmast_inquiry(msfun, &inquiry);
+	rc = usbmast_inquiry(mfun, &inquiry);
 	if (rc != EOK) {
 		usb_log_warning("Failed to inquire device `%s': %s.\n",
-		    dev->ddf_dev->name, str_error(rc));
+		    mdev->ddf_dev->name, str_error(rc));
 		rc = EIO;
 		goto error;
 	}
 
-	usb_log_info("Mass storage `%s': " \
-	    "%s by %s rev. %s is %s (%s), %zu LUN(s).\n",
-	    dev->ddf_dev->name,
+	usb_log_info("Mass storage `%s' LUN %u: " \
+	    "%s by %s rev. %s is %s (%s).\n",
+	    mdev->ddf_dev->name,
+	    lun,
 	    inquiry.product,
 	    inquiry.vendor,
 	    inquiry.revision,
 	    usbmast_scsi_dev_type_str(inquiry.device_type),
-	    inquiry.removable ? "removable" : "non-removable",
-	    lun_count);
+	    inquiry.removable ? "removable" : "non-removable");
 
 	uint32_t nblocks, block_size;
 
-	rc = usbmast_read_capacity(msfun, &nblocks, &block_size);
+	rc = usbmast_read_capacity(mfun, &nblocks, &block_size);
 	if (rc != EOK) {
 		usb_log_warning("Failed to read capacity, device `%s': %s.\n",
-		    dev->ddf_dev->name, str_error(rc));
+		    mdev->ddf_dev->name, str_error(rc));
 		rc = EIO;
 		goto error;
@@ -166,6 +209,6 @@
 	    "block_size=%" PRIu32 "\n", nblocks, block_size);
 
-	msfun->nblocks = nblocks;
-	msfun->block_size = block_size;
+	mfun->nblocks = nblocks;
+	mfun->block_size = block_size;
 
 	rc = ddf_fun_bind(fun);
@@ -182,6 +225,8 @@
 	if (fun != NULL)
 		ddf_fun_destroy(fun);
-	if (msfun != NULL)
-		free(msfun);
+	if (fun_name != NULL)
+		free(fun_name);
+	if (mfun != NULL)
+		free(mfun);
 	return rc;
 }
@@ -191,5 +236,5 @@
     void *arg)
 {
-	usbmast_fun_t *msfun;
+	usbmast_fun_t *mfun;
 	void *comm_buf = NULL;
 	size_t comm_size;
@@ -217,5 +262,5 @@
 	(void) async_share_out_finalize(callid, comm_buf);
 
-	msfun = (usbmast_fun_t *) ((ddf_fun_t *)arg)->driver_data;
+	mfun = (usbmast_fun_t *) ((ddf_fun_t *)arg)->driver_data;
 
 	while (true) {
@@ -231,14 +276,14 @@
 		switch (method) {
 		case BD_GET_BLOCK_SIZE:
-			async_answer_1(callid, EOK, msfun->block_size);
+			async_answer_1(callid, EOK, mfun->block_size);
 			break;
 		case BD_GET_NUM_BLOCKS:
-			async_answer_2(callid, EOK, LOWER32(msfun->nblocks),
-			    UPPER32(msfun->nblocks));
+			async_answer_2(callid, EOK, LOWER32(mfun->nblocks),
+			    UPPER32(mfun->nblocks));
 			break;
 		case BD_READ_BLOCKS:
 			ba = MERGE_LOUP32(IPC_GET_ARG1(call), IPC_GET_ARG2(call));
 			cnt = IPC_GET_ARG3(call);
-			retval = usbmast_read(msfun, ba, cnt, comm_buf);
+			retval = usbmast_read(mfun, ba, cnt, comm_buf);
 			async_answer_0(callid, retval);
 			break;
@@ -246,5 +291,5 @@
 			ba = MERGE_LOUP32(IPC_GET_ARG1(call), IPC_GET_ARG2(call));
 			cnt = IPC_GET_ARG3(call);
-			retval = usbmast_write(msfun, ba, cnt, comm_buf);
+			retval = usbmast_write(mfun, ba, cnt, comm_buf);
 			async_answer_0(callid, retval);
 			break;
