From: Simon Glass Date: Wed, 21 Sep 2022 14:21:36 +0000 (+0200) Subject: scsi: Move core emulation state into a new struct X-Git-Url: http://git.dujemihanovic.xyz/?a=commitdiff_plain;h=1377d448a26aa67907ae86a84d33c02c7c9b9dcd;p=u-boot.git scsi: Move core emulation state into a new struct In preparation for sharing the emulation code between two drivers, move some of the fields into a new struct. Use a separate header file so it can be used by various drivers. Signed-off-by: Simon Glass --- diff --git a/drivers/usb/emul/sandbox_flash.c b/drivers/usb/emul/sandbox_flash.c index 806aed2ef2..e7abc0d5c9 100644 --- a/drivers/usb/emul/sandbox_flash.c +++ b/drivers/usb/emul/sandbox_flash.c @@ -9,6 +9,7 @@ #include #include #include +#include #include /* @@ -34,28 +35,21 @@ enum { /** * struct sandbox_flash_priv - private state for this driver * + * @eminfo: emulator state * @error: true if there is an error condition - * @alloc_len: Allocation length from the last incoming command - * @transfer_len: Transfer length from CBW header - * @read_len: Number of bytes of data left in the current read command * @tag: Tag value from last command * @fd: File descriptor of backing file * @file_size: Size of file in bytes * @status_buff: Data buffer for outgoing status - * @buff_used: Number of bytes ready to transfer back to host * @buff: Data buffer for outgoing data */ struct sandbox_flash_priv { + struct scsi_emul_info eminfo; bool error; - int alloc_len; - int transfer_len; - int read_len; - enum scsi_cmd_phase phase; u32 tag; int fd; loff_t file_size; struct umass_bbb_csw status; - int buff_used; u8 buff[512]; }; @@ -188,13 +182,14 @@ static int sandbox_flash_control(struct udevice *dev, struct usb_device *udev, static void setup_fail_response(struct sandbox_flash_priv *priv) { + struct scsi_emul_info *info = &priv->eminfo; struct umass_bbb_csw *csw = &priv->status; csw->dCSWSignature = CSWSIGNATURE; csw->dCSWTag = priv->tag; csw->dCSWDataResidue = 0; csw->bCSWStatus = CSWSTATUS_FAILED; - priv->buff_used = 0; + info->buff_used = 0; } /** @@ -207,6 +202,7 @@ static void setup_fail_response(struct sandbox_flash_priv *priv) static void setup_response(struct sandbox_flash_priv *priv, void *resp, int size) { + struct scsi_emul_info *info = &priv->eminfo; struct umass_bbb_csw *csw = &priv->status; csw->dCSWSignature = CSWSIGNATURE; @@ -215,14 +211,16 @@ static void setup_response(struct sandbox_flash_priv *priv, void *resp, csw->bCSWStatus = CSWSTATUS_GOOD; assert(!resp || resp == priv->buff); - priv->buff_used = size; + info->buff_used = size; } static void 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); - priv->read_len = transfer_len; + info->read_len = transfer_len; if (priv->fd != -1) { os_lseek(priv->fd, lba * SANDBOX_FLASH_BLOCK_LEN, OS_SEEK_SET); setup_response(priv, priv->buff, @@ -236,13 +234,14 @@ static int handle_ufi_command(struct sandbox_flash_plat *plat, struct sandbox_flash_priv *priv, const void *buff, int len) { + struct scsi_emul_info *info = &priv->eminfo; const struct scsi_cmd *req = buff; switch (*req->cmd) { case SCSI_INQUIRY: { struct scsi_inquiry_resp *resp = (void *)priv->buff; - priv->alloc_len = req->cmd[4]; + info->alloc_len = req->cmd[4]; memset(resp, '\0', sizeof(*resp)); resp->data_format = 1; resp->additional_len = 0x1f; @@ -284,7 +283,7 @@ static int handle_ufi_command(struct sandbox_flash_plat *plat, return -EPROTONOSUPPORT; } - priv->phase = priv->transfer_len ? SCSIPH_DATA : SCSIPH_STATUS; + info->phase = info->transfer_len ? SCSIPH_DATA : SCSIPH_STATUS; return 0; } @@ -293,17 +292,18 @@ static int sandbox_flash_bulk(struct udevice *dev, struct usb_device *udev, { 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); struct umass_bbb_cbw *cbw = buff; debug("%s: dev=%s, pipe=%lx, ep=%x, len=%x, phase=%d\n", __func__, - dev->name, pipe, ep, len, priv->phase); + dev->name, pipe, ep, len, info->phase); switch (ep) { case SANDBOX_FLASH_EP_OUT: - switch (priv->phase) { + switch (info->phase) { case SCSIPH_START: - priv->alloc_len = 0; - priv->read_len = 0; + info->alloc_len = 0; + info->read_len = 0; if (priv->error || len != UMASS_BBB_CBW_SIZE || cbw->dCBWSignature != CBWSIGNATURE) goto err; @@ -312,7 +312,7 @@ static int sandbox_flash_bulk(struct udevice *dev, struct usb_device *udev, goto err; if (cbw->bCDBLength < 1 || cbw->bCDBLength >= 0x10) goto err; - priv->transfer_len = cbw->dCBWDataTransferLength; + info->transfer_len = cbw->dCBWDataTransferLength; priv->tag = cbw->dCBWTag; return handle_ufi_command(plat, priv, cbw->CBWCDB, cbw->bCDBLength); @@ -323,11 +323,11 @@ static int sandbox_flash_bulk(struct udevice *dev, struct usb_device *udev, break; } case SANDBOX_FLASH_EP_IN: - switch (priv->phase) { + switch (info->phase) { case SCSIPH_DATA: - debug("data in, len=%x, alloc_len=%x, priv->read_len=%x\n", - len, priv->alloc_len, priv->read_len); - if (priv->read_len) { + debug("data in, len=%x, alloc_len=%x, info->read_len=%x\n", + len, info->alloc_len, info->read_len); + if (info->read_len) { ulong bytes_read; if (priv->fd == -1) @@ -336,16 +336,16 @@ static int sandbox_flash_bulk(struct udevice *dev, struct usb_device *udev, bytes_read = os_read(priv->fd, buff, len); if (bytes_read != len) return -EIO; - priv->read_len -= len / SANDBOX_FLASH_BLOCK_LEN; - if (!priv->read_len) - priv->phase = SCSIPH_STATUS; + info->read_len -= len / SANDBOX_FLASH_BLOCK_LEN; + if (!info->read_len) + info->phase = SCSIPH_STATUS; } else { - if (priv->alloc_len && len > priv->alloc_len) - len = priv->alloc_len; + if (info->alloc_len && len > info->alloc_len) + len = info->alloc_len; if (len > sizeof(priv->buff)) len = sizeof(priv->buff); memcpy(buff, priv->buff, len); - priv->phase = SCSIPH_STATUS; + info->phase = SCSIPH_STATUS; } return len; case SCSIPH_STATUS: @@ -353,7 +353,7 @@ static int sandbox_flash_bulk(struct udevice *dev, struct usb_device *udev, if (len > sizeof(priv->status)) len = sizeof(priv->status); memcpy(buff, &priv->status, len); - priv->phase = SCSIPH_START; + info->phase = SCSIPH_START; return len; default: break; diff --git a/include/scsi_emul.h b/include/scsi_emul.h new file mode 100644 index 0000000000..dec78d239c --- /dev/null +++ b/include/scsi_emul.h @@ -0,0 +1,32 @@ +/* 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 + * + * implementations of SCSI functions required so that CONFIG_SCSI can be enabled + * for sandbox + */ + +#ifndef __scsi_emul_h +#define __scsi_emul_h + +/** + * struct scsi_emul_info - information for emulating a SCSI device + * + * @phase: Current SCSI phase + * @buff_used: Number of bytes ready to transfer back to host + * @read_len: Number of bytes of data left in the current read command + * @alloc_len: Allocation length from the last incoming command + * @transfer_len: Transfer length from CBW header + */ +struct scsi_emul_info { + enum scsi_cmd_phase phase; + int buff_used; + int read_len; + int alloc_len; + uint transfer_len; +}; + +#endif