Index: uspace/drv/bus/usb/usbmast/bo_trans.c
===================================================================
--- uspace/drv/bus/usb/usbmast/bo_trans.c	(revision 2aceec5d8eb06e4d99d0b4a64ba26b6db7f1938f)
+++ uspace/drv/bus/usb/usbmast/bo_trans.c	(revision 45cae6bbf4f84066a068fe7e627bf07f0f23c75e)
@@ -64,4 +64,5 @@
  * @param dbuf_size	Size of the data buffer
  * @param xferred_size	Number of bytes actually transferred
+ * @param cmd_status	Command status
  *
  * @return		Error code
@@ -69,7 +70,8 @@
 static int usb_massstor_cmd(usbmast_fun_t *mfun, uint32_t tag, const void *cmd,
     size_t cmd_size, usb_direction_t ddir, void *dbuf, size_t dbuf_size,
-    size_t *xferred_size)
+    size_t *xferred_size, cmd_status_t *cmd_status)
 {
 	int rc;
+	int retval = EOK;
 	size_t act_size;
 	usb_pipe_t *bulk_in_pipe = mfun->mdev->usb_dev->pipes[BULK_IN_EP].pipe;
@@ -82,12 +84,13 @@
 
 	/* Send the CBW. */
+	MASTLOG("Sending CBW.\n");
 	rc = usb_pipe_write(bulk_out_pipe, &cbw, sizeof(cbw));
 	MASTLOG("CBW '%s' sent: %s.\n",
 	    usb_debug_str_buffer((uint8_t *) &cbw, sizeof(cbw), 0),
 	    str_error(rc));
-	if (rc != EOK) {
-		return rc;
-	}
-
+	if (rc != EOK)
+		return EIO;
+
+	MASTLOG("Transferring data.\n");
 	if (ddir == USB_DIRECTION_IN) {
 		/* Recieve data from the device. */
@@ -104,10 +107,15 @@
 	}
 
-	if (rc != EOK) {
-		/*
-		 * XXX If the pipe is stalled, we should clear it
-		 * and read CSW.
-		 */
-		return rc;
+	if (rc == ESTALL) {
+		/* Clear stall condition and continue below to read CSW. */
+		if (ddir == USB_DIRECTION_IN) {
+			usb_pipe_clear_halt(&mfun->mdev->usb_dev->ctrl_pipe,
+			    mfun->mdev->usb_dev->pipes[BULK_IN_EP].pipe);
+		} else {
+			usb_pipe_clear_halt(&mfun->mdev->usb_dev->ctrl_pipe,
+			    mfun->mdev->usb_dev->pipes[BULK_OUT_EP].pipe);
+		}
+        } else if (rc != EOK) {
+		return EIO;
 	}
 
@@ -115,4 +123,5 @@
 	usb_massstor_csw_t csw;
 	size_t csw_size;
+	MASTLOG("Reading CSW.\n");
 	rc = usb_pipe_read(bulk_in_pipe, &csw, sizeof(csw), &csw_size);
 	MASTLOG("CSW '%s' received (%zu bytes): %s.\n",
@@ -121,15 +130,15 @@
 	if (rc != EOK) {
 		MASTLOG("rc != EOK\n");
-		return rc;
+		return EIO;
 	}
 
 	if (csw_size != sizeof(csw)) {
 		MASTLOG("csw_size != sizeof(csw)\n");
-		return ERANGE;
+		return EIO;
 	}
 
 	if (csw.dCSWTag != tag) {
 		MASTLOG("csw.dCSWTag != tag\n");
-		return EBADCHECKSUM;
+		return EIO;
 	}
 
@@ -137,9 +146,19 @@
 	 * Determine the actual return value from the CSW.
 	 */
-	if (csw.dCSWStatus != 0) {
-		MASTLOG("csw.dCSWStatus != 0\n");
-		// FIXME: better error code
-		// FIXME: distinguish 0x01 and 0x02
-		return EXDEV;
+	switch (csw.dCSWStatus) {
+	case cbs_passed:
+		*cmd_status = CMDS_GOOD;
+		break;
+	case cbs_failed:
+		MASTLOG("Command failed\n");
+		*cmd_status = CMDS_FAILED;
+		break;
+	case cbs_phase_error:
+		MASTLOG("Phase error\n");
+		retval = EIO;
+		break;
+	default:
+		retval = EIO;
+		break;
 	}
 
@@ -147,5 +166,5 @@
 	if (residue > dbuf_size) {
 		MASTLOG("residue > dbuf_size\n");
-		return ERANGE;
+		return EIO;
 	}
 
@@ -161,5 +180,5 @@
 		*xferred_size = dbuf_size - residue;
 
-	return EOK;
+	return retval;
 }
 
@@ -174,12 +193,14 @@
  * @param dbuf_size	Data receive buffer size in bytes
  * @param proc_size	Number of bytes actually processed by device
+ * @param cmd_status	Command status
  *
  * @return Error code
  */
 int usb_massstor_data_in(usbmast_fun_t *mfun, uint32_t tag, const void *cmd,
-    size_t cmd_size, void *dbuf, size_t dbuf_size, size_t *proc_size)
+    size_t cmd_size, void *dbuf, size_t dbuf_size, size_t *proc_size,
+    cmd_status_t *cmd_status)
 {
 	return usb_massstor_cmd(mfun, tag, cmd, cmd_size, USB_DIRECTION_IN,
-	    dbuf, dbuf_size, proc_size);
+	    dbuf, dbuf_size, proc_size, cmd_status);
 }
 
@@ -194,12 +215,14 @@
  * @param data_size	Size of @a data in bytes
  * @param proc_size	Number of bytes actually processed by device
+ * @param cmd_status	Command status
  *
  * @return Error code
  */
 int usb_massstor_data_out(usbmast_fun_t *mfun, uint32_t tag, const void *cmd,
-    size_t cmd_size, const void *data, size_t data_size, size_t *proc_size)
+    size_t cmd_size, const void *data, size_t data_size, size_t *proc_size,
+    cmd_status_t *cmd_status)
 {
 	return usb_massstor_cmd(mfun, tag, cmd, cmd_size, USB_DIRECTION_OUT,
-	    (void *) data, data_size, proc_size);
+	    (void *) data, data_size, proc_size, cmd_status);
 }
 
Index: uspace/drv/bus/usb/usbmast/bo_trans.h
===================================================================
--- uspace/drv/bus/usb/usbmast/bo_trans.h	(revision 2aceec5d8eb06e4d99d0b4a64ba26b6db7f1938f)
+++ uspace/drv/bus/usb/usbmast/bo_trans.h	(revision 45cae6bbf4f84066a068fe7e627bf07f0f23c75e)
@@ -47,8 +47,13 @@
 #define BULK_OUT_EP 1
 
+typedef enum cmd_status {
+	CMDS_GOOD,
+	CMDS_FAILED
+} cmd_status_t;
+
 extern int usb_massstor_data_in(usbmast_fun_t *, uint32_t, const void *,
-    size_t, void *, size_t, size_t *);
+    size_t, void *, size_t, size_t *, cmd_status_t *);
 extern int usb_massstor_data_out(usbmast_fun_t *, uint32_t, const void *,
-    size_t, const void *, size_t, size_t *);
+    size_t, const void *, size_t, size_t *, cmd_status_t *);
 extern int usb_massstor_reset(usbmast_dev_t *);
 extern void usb_massstor_reset_recovery(usbmast_dev_t *);
Index: uspace/drv/bus/usb/usbmast/cmdw.h
===================================================================
--- uspace/drv/bus/usb/usbmast/cmdw.h	(revision 2aceec5d8eb06e4d99d0b4a64ba26b6db7f1938f)
+++ uspace/drv/bus/usb/usbmast/cmdw.h	(revision 45cae6bbf4f84066a068fe7e627bf07f0f23c75e)
@@ -57,4 +57,10 @@
 } __attribute__((packed)) usb_massstor_csw_t;
 
+enum cmd_block_status {
+	cbs_passed	= 0x00,
+	cbs_failed	= 0x01,
+	cbs_phase_error = 0x02
+};
+
 extern void usb_massstor_cbw_prepare(usb_massstor_cbw_t *, uint32_t, uint32_t,
     usb_direction_t, uint8_t, uint8_t, const uint8_t *);
Index: uspace/drv/bus/usb/usbmast/scsi_ms.c
===================================================================
--- uspace/drv/bus/usb/usbmast/scsi_ms.c	(revision 2aceec5d8eb06e4d99d0b4a64ba26b6db7f1938f)
+++ uspace/drv/bus/usb/usbmast/scsi_ms.c	(revision 45cae6bbf4f84066a068fe7e627bf07f0f23c75e)
@@ -61,4 +61,20 @@
 }
 
+static void usbmast_dump_sense(usbmast_fun_t *mfun)
+{
+	scsi_sense_data_t sense_buf;
+	int rc;
+
+	rc = usbmast_request_sense(mfun, &sense_buf, sizeof(sense_buf));
+	if (rc == EOK) {
+		printf("Got sense data (sense_key=0x%x, asc=0x%02x, "
+		    "ascq=0x%02x.\n", sense_buf.flags_key & 0x0f,
+		    sense_buf.additional_code,
+		    sense_buf.additional_cqual);
+	} else {
+		printf("Failed to read sense data.\n");
+	}
+}
+
 /** Perform SCSI Inquiry command on USB mass storage device.
  *
@@ -72,4 +88,5 @@
 	size_t response_len;
 	scsi_cdb_inquiry_t cdb;
+	cmd_status_t status;
 	int rc;
 
@@ -79,10 +96,17 @@
 
 	rc = usb_massstor_data_in(mfun, 0xDEADBEEF, (uint8_t *) &cdb,
-	    sizeof(cdb), &inq_data, sizeof(inq_data), &response_len);
+	    sizeof(cdb), &inq_data, sizeof(inq_data), &response_len, &status);
 
 	if (rc != EOK) {
-		usb_log_error("Inquiry failed, device %s: %s.\n",
-		   mfun->mdev->ddf_dev->name, str_error(rc));
-		return rc;
+		usb_log_error("Inquiry transport failed, device %s: %s.\n",
+		   mfun->mdev->ddf_dev->name, str_error(rc));
+		return rc;
+	}
+
+	if (status != CMDS_GOOD) {
+		usb_log_error("Inquiry command failed, device %s.\n",
+		   mfun->mdev->ddf_dev->name);
+		usbmast_dump_sense(mfun);
+		return EIO;
 	}
 
@@ -129,4 +153,5 @@
 	scsi_cdb_request_sense_t cdb;
 	size_t data_len;
+	cmd_status_t status;
 	int rc;
 
@@ -136,7 +161,7 @@
 
 	rc = usb_massstor_data_in(mfun, 0xDEADBEEF, (uint8_t *) &cdb,
-	    sizeof(cdb), buf, size, &data_len);
-
-        if (rc != EOK) {
+	    sizeof(cdb), buf, size, &data_len, &status);
+
+        if (rc != EOK || status != CMDS_GOOD) {
 		usb_log_error("Request Sense failed, device %s: %s.\n",
 		   mfun->mdev->ddf_dev->name, str_error(rc));
@@ -167,4 +192,5 @@
 	scsi_read_capacity_10_data_t data;
 	size_t data_len;
+	cmd_status_t status;
 	int rc;
 
@@ -173,10 +199,17 @@
 
 	rc = usb_massstor_data_in(mfun, 0xDEADBEEF, (uint8_t *) &cdb,
-	    sizeof(cdb), &data, sizeof(data), &data_len);
+	    sizeof(cdb), &data, sizeof(data), &data_len, &status);
 
         if (rc != EOK) {
-		usb_log_error("Read Capacity (10) failed, device %s: %s.\n",
-		   mfun->mdev->ddf_dev->name, str_error(rc));
-		return rc;
+		usb_log_error("Read Capacity (10) transport failed, device %s: %s.\n",
+		   mfun->mdev->ddf_dev->name, str_error(rc));
+		return rc;
+	}
+
+	if (status != CMDS_GOOD) {
+		usb_log_error("Read Capacity (10) command failed, device %s.\n",
+		   mfun->mdev->ddf_dev->name);
+		usbmast_dump_sense(mfun);
+		return EIO;
 	}
 
@@ -205,4 +238,5 @@
 	scsi_cdb_read_12_t cdb;
 	size_t data_len;
+	cmd_status_t status;
 	int rc;
 
@@ -221,10 +255,17 @@
 
 	rc = usb_massstor_data_in(mfun, 0xDEADBEEF, (uint8_t *) &cdb,
-	    sizeof(cdb), buf, nblocks * mfun->block_size, &data_len);
+	    sizeof(cdb), buf, nblocks * mfun->block_size, &data_len, &status);
 
         if (rc != EOK) {
-		usb_log_error("Read (12) failed, device %s: %s.\n",
-		   mfun->mdev->ddf_dev->name, str_error(rc));
-		return rc;
+		usb_log_error("Read (12) transport failed, device %s: %s.\n",
+		   mfun->mdev->ddf_dev->name, str_error(rc));
+		return rc;
+	}
+
+	if (status != CMDS_GOOD) {
+		usb_log_error("Read (12) command failed, device %s.\n",
+		   mfun->mdev->ddf_dev->name);
+		usbmast_dump_sense(mfun);
+		return EIO;
 	}
 
@@ -252,4 +293,5 @@
 	scsi_cdb_write_12_t cdb;
 	size_t sent_len;
+	cmd_status_t status;
 	int rc;
 
@@ -266,10 +308,17 @@
 
 	rc = usb_massstor_data_out(mfun, 0xDEADBEEF, (uint8_t *) &cdb,
-	    sizeof(cdb), data, nblocks * mfun->block_size, &sent_len);
+	    sizeof(cdb), data, nblocks * mfun->block_size, &sent_len, &status);
 
         if (rc != EOK) {
-		usb_log_error("Write (12) failed, device %s: %s.\n",
-		   mfun->mdev->ddf_dev->name, str_error(rc));
-		return rc;
+		usb_log_error("Write (12) transport failed, device %s: %s.\n",
+		   mfun->mdev->ddf_dev->name, str_error(rc));
+		return rc;
+	}
+
+	if (status != CMDS_GOOD) {
+		usb_log_error("Write (12) command failed, device %s.\n",
+		   mfun->mdev->ddf_dev->name);
+		usbmast_dump_sense(mfun);
+		return EIO;
 	}
 
