Add test coverage for blk_write() as well.

The blk_erase() is not tested for now as the USB stor interface does not
support erase.

Signed-off-by: Simon Glass <s...@chromium.org>
---

 drivers/scsi/scsi_emul.c         |  9 ++++++++
 drivers/usb/emul/sandbox_flash.c | 35 ++++++++++++++++++++++++++++----
 include/scsi.h                   | 10 +++++++++
 include/scsi_emul.h              | 16 +++++++++++----
 test/dm/usb.c                    | 19 ++++++++++++++++-
 5 files changed, 80 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/scsi_emul.c b/drivers/scsi/scsi_emul.c
index 5ba364bdac7..6b8468f7994 100644
--- a/drivers/scsi/scsi_emul.c
+++ b/drivers/scsi/scsi_emul.c
@@ -62,6 +62,15 @@ int sb_scsi_emul_command(struct scsi_emul_info *info,
                ret = SCSI_EMUL_DO_READ;
                break;
        }
+       case SCSI_WRITE10: {
+               const struct scsi_write10_req *write_req = (void *)req;
+
+               info->seek_block = be32_to_cpu(write_req->lba);
+               info->write_len = be16_to_cpu(write_req->xfer_len);
+               info->buff_used = info->write_len * info->block_size;
+               ret = SCSI_EMUL_DO_WRITE;
+               break;
+       }
        default:
                debug("Command not supported: %x\n", req->cmd[0]);
                ret = -EPROTONOSUPPORT;
diff --git a/drivers/usb/emul/sandbox_flash.c b/drivers/usb/emul/sandbox_flash.c
index 2589c708d88..6e8cfe1650a 100644
--- a/drivers/usb/emul/sandbox_flash.c
+++ b/drivers/usb/emul/sandbox_flash.c
@@ -4,6 +4,8 @@
  * Written by Simon Glass <s...@chromium.org>
  */
 
+#define LOG_CATEGORY   UCLASS_USB
+
 #include <common.h>
 #include <dm.h>
 #include <log.h>
@@ -190,7 +192,8 @@ static int handle_ufi_command(struct sandbox_flash_priv 
*priv, const void *buff,
        ret = sb_scsi_emul_command(info, req, len);
        if (!ret) {
                setup_response(priv);
-       } else if (ret == SCSI_EMUL_DO_READ && priv->fd != -1) {
+       } else if ((ret == SCSI_EMUL_DO_READ || ret == SCSI_EMUL_DO_WRITE) &&
+                  priv->fd != -1) {
                os_lseek(priv->fd, info->seek_block * info->block_size,
                         OS_SEEK_SET);
                setup_response(priv);
@@ -217,6 +220,7 @@ static int sandbox_flash_bulk(struct udevice *dev, struct 
usb_device *udev,
                case SCSIPH_START:
                        info->alloc_len = 0;
                        info->read_len = 0;
+                       info->write_len = 0;
                        if (priv->error || len != UMASS_BBB_CBW_SIZE ||
                            cbw->dCBWSignature != CBWSIGNATURE)
                                goto err;
@@ -230,8 +234,31 @@ static int sandbox_flash_bulk(struct udevice *dev, struct 
usb_device *udev,
                        return handle_ufi_command(priv, cbw->CBWCDB,
                                                  cbw->bCDBLength);
                case SCSIPH_DATA:
-                       debug("data out\n");
-                       break;
+                       log_debug("data out, len=%x, info->write_len=%x\n", len,
+                                 info->write_len);
+                       info->transfer_len = cbw->dCBWDataTransferLength;
+                       priv->tag = cbw->dCBWTag;
+                       if (!info->write_len)
+                               return 0;
+                       if (priv->fd != -1) {
+                               ulong bytes_written;
+
+                               bytes_written = os_write(priv->fd, buff, len);
+                               log_debug("bytes_written=%lx", bytes_written);
+                               if (bytes_written != len)
+                                       return -EIO;
+                               info->write_len -= len / info->block_size;
+                               if (!info->write_len)
+                                       info->phase = SCSIPH_STATUS;
+                       } else {
+                               if (info->alloc_len && len > info->alloc_len)
+                                       len = info->alloc_len;
+                               if (len > SANDBOX_FLASH_BUF_SIZE)
+                                       len = SANDBOX_FLASH_BUF_SIZE;
+                               memcpy(info->buff, buff, len);
+                               info->phase = SCSIPH_STATUS;
+                       }
+                       return len;
                default:
                        break;
                }
@@ -310,7 +337,7 @@ static int sandbox_flash_probe(struct udevice *dev)
        struct scsi_emul_info *info = &priv->eminfo;
        int ret;
 
-       priv->fd = os_open(plat->pathname, OS_O_RDONLY);
+       priv->fd = os_open(plat->pathname, OS_O_RDWR);
        if (priv->fd != -1) {
                ret = os_get_filesize(plat->pathname, &info->file_size);
                if (ret)
diff --git a/include/scsi.h b/include/scsi.h
index d8f0d9c7dcd..6f396c389cf 100644
--- a/include/scsi.h
+++ b/include/scsi.h
@@ -199,6 +199,16 @@ struct __packed scsi_read10_req {
        u8 spare2[3];
 };
 
+/** struct scsi_write10_req - data for the write10 command */
+struct __packed scsi_write10_req {
+       u8 cmd;
+       u8 lun_flags;
+       u32 lba;
+       u8 spare;
+       u16 xfer_len;
+       u8 spare2[3];
+};
+
 /**
  * struct scsi_plat - stores information about SCSI controller
  *
diff --git a/include/scsi_emul.h b/include/scsi_emul.h
index a55311d59bc..d439f7c00c2 100644
--- a/include/scsi_emul.h
+++ b/include/scsi_emul.h
@@ -41,13 +41,20 @@ struct scsi_emul_info {
        enum scsi_cmd_phase phase;
        int buff_used;
        int read_len;
+       int write_len;
        uint seek_pos;
        int alloc_len;
        uint transfer_len;
 };
 
-/* Indicates that a read is being started */
-#define SCSI_EMUL_DO_READ      1
+/**
+ * Return value from sb_scsi_emul_command() indicates that a read or write is
+ * being started
+ */
+enum {
+       SCSI_EMUL_DO_READ       = 1,
+       SCSI_EMUL_DO_WRITE      = 2,
+};
 
 /**
  * sb_scsi_emul_command() - Process a SCSI command
@@ -61,8 +68,9 @@ struct scsi_emul_info {
  * @info: Emulation information
  * @req: Request to process
  * @len: Length of request in bytes
- * @return SCSI_EMUL_DO_READ if a read has started, 0 if some other operation
- *     has start, -ve if there was an error
+ * @return SCSI_EMUL_DO_READ if a read has started, SCSI_EMUL_DO_WRITE if a
+ *     write has started, 0 if some other operation has started, -ve if there
+ *     was an error
  */
 int sb_scsi_emul_command(struct scsi_emul_info *info,
                         const struct scsi_cmd *req, int len);
diff --git a/test/dm/usb.c b/test/dm/usb.c
index 445b21a560b..7671ef156d8 100644
--- a/test/dm/usb.c
+++ b/test/dm/usb.c
@@ -61,7 +61,24 @@ static int dm_test_usb_flash(struct unit_test_state *uts)
        ut_asserteq(512, dev_desc->blksz);
        memset(cmp, '\0', sizeof(cmp));
        ut_asserteq(2, blk_read(blk, 0, 2, cmp));
-       ut_assertok(strcmp(cmp, "this is a test"));
+       ut_asserteq_str("this is a test", cmp);
+
+       strcpy(cmp, "another test");
+       ut_asserteq(1, blk_write(blk, 1, 1, cmp));
+
+       memset(cmp, '\0', sizeof(cmp));
+       ut_asserteq(2, blk_read(blk, 0, 2, cmp));
+       ut_asserteq_str("this is a test", cmp);
+       ut_asserteq_str("another test", cmp + 512);
+
+       memset(cmp, '\0', sizeof(cmp));
+       ut_asserteq(1, blk_write(blk, 1, 1, cmp));
+
+       memset(cmp, '\0', sizeof(cmp));
+       ut_asserteq(2, blk_read(blk, 0, 2, cmp));
+       ut_asserteq_str("this is a test", cmp);
+       ut_asserteq_str("", cmp + 512);
+
        ut_assertok(usb_stop());
 
        return 0;
-- 
2.37.3.998.g577e59143f-goog

Reply via email to