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 <sjg@chromium.org>
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;
* Written by Simon Glass <sjg@chromium.org>
*/
+#define LOG_CATEGORY UCLASS_USB
+
#include <common.h>
#include <dm.h>
#include <log.h>
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);
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;
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;
}
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)
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
*
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
* @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 started, -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);
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;