u-boot.lists.denx.de archive mirror
 help / color / mirror / Atom feed
From: Simon Glass <sjg@chromium.org>
To: U-Boot Mailing List <u-boot@lists.denx.de>
Cc: Simon Glass <sjg@chromium.org>, Andrew Scull <ascull@google.com>,
	Marek Vasut <marex@denx.de>,
	Rob Herring <rob.herring@calxeda.com>,
	Sean Anderson <seanga2@gmail.com>, Stefan Roese <sr@denx.de>
Subject: [PATCH 13/15] sandbox: scsi: Move request-handling code to scsi_emul
Date: Sat, 27 Aug 2022 09:15:11 -0600	[thread overview]
Message-ID: <20220827151513.736395-14-sjg@chromium.org> (raw)
In-Reply-To: <20220827151513.736395-1-sjg@chromium.org>

Move this code into the emulator file so it can be used by multiple
drivers.

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

 drivers/scsi/Makefile            |  1 +
 drivers/scsi/scsi_emul.c         | 74 +++++++++++++++++++++++++++
 drivers/usb/emul/sandbox_flash.c | 87 ++++----------------------------
 include/scsi_emul.h              | 24 +++++++++
 4 files changed, 109 insertions(+), 77 deletions(-)
 create mode 100644 drivers/scsi/scsi_emul.c

diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 25194eeec11..d1b40c61401 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -17,4 +17,5 @@ endif
 
 ifdef CONFIG_SCSI
 obj-$(CONFIG_SANDBOX) += sandbox_scsi.o
+obj-$(CONFIG_SANDBOX) += scsi_emul.o
 endif
diff --git a/drivers/scsi/scsi_emul.c b/drivers/scsi/scsi_emul.c
new file mode 100644
index 00000000000..5ba364bdac7
--- /dev/null
+++ b/drivers/scsi/scsi_emul.c
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Emulation of enough SCSI commands to find and read from a unit
+ *
+ * Copyright 2022 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * implementation of SCSI functions required so that CONFIG_SCSI can be enabled
+ * for sandbox.
+ */
+
+#define LOG_CATEGORY UCLASS_SCSI
+
+#include <common.h>
+#include <dm.h>
+#include <log.h>
+#include <scsi.h>
+#include <scsi_emul.h>
+
+int sb_scsi_emul_command(struct scsi_emul_info *info,
+			 const struct scsi_cmd *req, int len)
+{
+	int ret = 0;
+
+	info->buff_used = 0;
+	log_debug("emul %x\n", *req->cmd);
+	switch (*req->cmd) {
+	case SCSI_INQUIRY: {
+		struct scsi_inquiry_resp *resp = (void *)info->buff;
+
+		info->alloc_len = req->cmd[4];
+		memset(resp, '\0', sizeof(*resp));
+		resp->data_format = 1;
+		resp->additional_len = 0x1f;
+		strncpy(resp->vendor, info->vendor, sizeof(resp->vendor));
+		strncpy(resp->product, info->product, sizeof(resp->product));
+		strncpy(resp->revision, "1.0", sizeof(resp->revision));
+		info->buff_used = sizeof(*resp);
+		break;
+	}
+	case SCSI_TST_U_RDY:
+		break;
+	case SCSI_RD_CAPAC: {
+		struct scsi_read_capacity_resp *resp = (void *)info->buff;
+		uint blocks;
+
+		if (info->file_size)
+			blocks = info->file_size / info->block_size - 1;
+		else
+			blocks = 0;
+		resp->last_block_addr = cpu_to_be32(blocks);
+		resp->block_len = cpu_to_be32(info->block_size);
+		info->buff_used = sizeof(*resp);
+		break;
+	}
+	case SCSI_READ10: {
+		const struct scsi_read10_req *read_req = (void *)req;
+
+		info->seek_block = be32_to_cpu(read_req->lba);
+		info->read_len = be16_to_cpu(read_req->xfer_len);
+		info->buff_used = info->read_len * info->block_size;
+		ret = SCSI_EMUL_DO_READ;
+		break;
+	}
+	default:
+		debug("Command not supported: %x\n", req->cmd[0]);
+		ret = -EPROTONOSUPPORT;
+	}
+	if (ret >= 0)
+		info->phase = info->transfer_len ? SCSIPH_DATA : SCSIPH_STATUS;
+	log_debug("   - done %x: ret=%d\n", *req->cmd, ret);
+
+	return ret;
+}
diff --git a/drivers/usb/emul/sandbox_flash.c b/drivers/usb/emul/sandbox_flash.c
index 2059fc7fe42..2589c708d88 100644
--- a/drivers/usb/emul/sandbox_flash.c
+++ b/drivers/usb/emul/sandbox_flash.c
@@ -180,97 +180,30 @@ static void setup_response(struct sandbox_flash_priv *priv)
 	csw->bCSWStatus = CSWSTATUS_GOOD;
 }
 
-/**
- * handle_read() - prepare for reading data from the backing file
- *
- * This seeks to the correct file position and sets info->buff_used to the
- * correct size.
- *
- * @priv: Private information
- * @lba: Start block to read from
- * @transfer_length: Number of blocks to read
- * @return 0 if OK, -EIO on failure
- */
-static int handle_read(struct sandbox_flash_priv *priv, ulong lba,
-		       ulong transfer_len)
-{
-	struct scsi_emul_info *info = &priv->eminfo;
-
-	debug("%s: lba=%lx, transfer_len=%lx\n", __func__, lba, transfer_len);
-	info->read_len = transfer_len;
-	if (priv->fd != -1) {
-		os_lseek(priv->fd, lba * info->block_size, OS_SEEK_SET);
-		info->buff_used = transfer_len * info->block_size;
-		return 0;
-	}
-
-	return -EIO;
-}
-
-static int handle_ufi_command(struct sandbox_flash_plat *plat,
-			      struct sandbox_flash_priv *priv, const void *buff,
+static int handle_ufi_command(struct sandbox_flash_priv *priv, const void *buff,
 			      int len)
 {
 	struct scsi_emul_info *info = &priv->eminfo;
 	const struct scsi_cmd *req = buff;
+	int ret;
 
-	info->buff_used = 0;
-	switch (*req->cmd) {
-	case SCSI_INQUIRY: {
-		struct scsi_inquiry_resp *resp = (void *)info->buff;
-
-		info->alloc_len = req->cmd[4];
-		memset(resp, '\0', sizeof(*resp));
-		resp->data_format = 1;
-		resp->additional_len = 0x1f;
-		strncpy(resp->vendor, info->vendor, sizeof(resp->vendor));
-		strncpy(resp->product, info->product, sizeof(resp->product));
-		strncpy(resp->revision, "1.0", sizeof(resp->revision));
-		info->buff_used = sizeof(*resp);
-		setup_response(priv);
-		break;
-	}
-	case SCSI_TST_U_RDY:
+	ret = sb_scsi_emul_command(info, req, len);
+	if (!ret) {
 		setup_response(priv);
-		break;
-	case SCSI_RD_CAPAC: {
-		struct scsi_read_capacity_resp *resp = (void *)info->buff;
-		uint blocks;
-
-		if (info->file_size)
-			blocks = info->file_size / info->block_size - 1;
-		else
-			blocks = 0;
-		resp->last_block_addr = cpu_to_be32(blocks);
-		resp->block_len = cpu_to_be32(info->block_size);
-		info->buff_used = sizeof(*resp);
+	} else if (ret == SCSI_EMUL_DO_READ && priv->fd != -1) {
+		os_lseek(priv->fd, info->seek_block * info->block_size,
+			 OS_SEEK_SET);
 		setup_response(priv);
-		break;
+	} else {
+		setup_fail_response(priv);
 	}
-	case SCSI_READ10: {
-		struct scsi_read10_req *req = (void *)buff;
 
-		if (!handle_read(priv, be32_to_cpu(req->lba),
-				 be16_to_cpu(req->xfer_len)))
-			setup_response(priv);
-		else
-			setup_fail_response(priv);
-
-		break;
-	}
-	default:
-		debug("Command not supported: %x\n", req->cmd[0]);
-		return -EPROTONOSUPPORT;
-	}
-
-	info->phase = info->transfer_len ? SCSIPH_DATA : SCSIPH_STATUS;
 	return 0;
 }
 
 static int sandbox_flash_bulk(struct udevice *dev, struct usb_device *udev,
 			      unsigned long pipe, void *buff, int len)
 {
-	struct sandbox_flash_plat *plat = dev_get_plat(dev);
 	struct sandbox_flash_priv *priv = dev_get_priv(dev);
 	struct scsi_emul_info *info = &priv->eminfo;
 	int ep = usb_pipeendpoint(pipe);
@@ -294,7 +227,7 @@ static int sandbox_flash_bulk(struct udevice *dev, struct usb_device *udev,
 				goto err;
 			info->transfer_len = cbw->dCBWDataTransferLength;
 			priv->tag = cbw->dCBWTag;
-			return handle_ufi_command(plat, priv, cbw->CBWCDB,
+			return handle_ufi_command(priv, cbw->CBWCDB,
 						  cbw->bCDBLength);
 		case SCSIPH_DATA:
 			debug("data out\n");
diff --git a/include/scsi_emul.h b/include/scsi_emul.h
index 3c52398e3ff..a55311d59bc 100644
--- a/include/scsi_emul.h
+++ b/include/scsi_emul.h
@@ -19,6 +19,7 @@
  * @product: Product name
  * @block_size: Block size of device in bytes (normally 512)
  * @file_size: Size of the backing file for this emulator, in bytes
+ * @seek_block: Seek position for file (block number)
  *
  * @phase: Current SCSI phase
  * @buff_used: Number of bytes ready to transfer back to host
@@ -34,13 +35,36 @@ struct scsi_emul_info {
 	const char *product;
 	int block_size;
 	loff_t file_size;
+	int seek_block;
 
 	/* state maintained by the emulator: */
 	enum scsi_cmd_phase phase;
 	int buff_used;
 	int read_len;
+	uint seek_pos;
 	int alloc_len;
 	uint transfer_len;
 };
 
+/* Indicates that a read is being started */
+#define SCSI_EMUL_DO_READ	1
+
+/**
+ * sb_scsi_emul_command() - Process a SCSI command
+ *
+ * This sets up the response in info->buff and updates various other values
+ * in info.
+ *
+ * If SCSI_EMUL_DO_READ is returned then the caller should set up so that the
+ * backing file can be read, or return an error status if there is no file.
+ *
+ * @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
+ */
+int sb_scsi_emul_command(struct scsi_emul_info *info,
+			 const struct scsi_cmd *req, int len);
+
 #endif
-- 
2.37.2.672.g94769d06f0-goog


  parent reply	other threads:[~2022-08-27 15:17 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-08-27 15:14 [PATCH 00/15] scsi: Convert sandbox SCSI to driver model Simon Glass
2022-08-27 15:14 ` [PATCH 01/15] scsi: Tidy up comments for struct scsi_cmd Simon Glass
2022-08-29 14:49   ` Heinrich Schuchardt
2022-08-27 15:15 ` [PATCH 02/15] sandbox: usb: Rename transfer_len in protocol struct Simon Glass
2022-08-27 15:15 ` [PATCH 03/15] scsi: Move cmd_phase enum to the header Simon Glass
2022-08-29 14:50   ` Heinrich Schuchardt
2022-08-27 15:15 ` [PATCH 04/15] scsi: Move core emulation state into a new struct Simon Glass
2022-08-27 15:15 ` [PATCH 05/15] sandbox: Move buffer to scsi_emul_info Simon Glass
2022-08-27 15:15 ` [PATCH 06/15] scsi: Move vendor/product info into the shared struct Simon Glass
2022-08-27 15:15 ` [PATCH 07/15] sandbox: scsi: Move block size into " Simon Glass
2022-08-27 15:15 ` [PATCH 08/15] sandbox: scsi: Move file " Simon Glass
2022-08-27 15:15 ` [PATCH 09/15] sandbox: scsi: Move reply setup out of helper Simon Glass
2022-08-27 15:15 ` [PATCH 10/15] sandbox: scsi: Remove setup calls from handle_read() Simon Glass
2022-08-27 15:15 ` [PATCH 11/15] sandbox: scsi: Move structs to header file Simon Glass
2022-08-29 14:51   ` Heinrich Schuchardt
2022-08-27 15:15 ` [PATCH 12/15] sandbox: Enable SCSI for all builds Simon Glass
2022-08-27 15:15 ` Simon Glass [this message]
2022-08-27 15:15 ` [PATCH 14/15] sandbox: Convert to use driver model for SCSI Simon Glass
2022-08-27 15:15 ` [PATCH 15/15] sandbox: Add a test " Simon Glass

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220827151513.736395-14-sjg@chromium.org \
    --to=sjg@chromium.org \
    --cc=ascull@google.com \
    --cc=marex@denx.de \
    --cc=rob.herring@calxeda.com \
    --cc=seanga2@gmail.com \
    --cc=sr@denx.de \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).