5ba364bdac756aafce7efcaaddb35b5b5a4612e9
[platform/kernel/u-boot.git] / drivers / scsi / scsi_emul.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Emulation of enough SCSI commands to find and read from a unit
4  *
5  * Copyright 2022 Google LLC
6  * Written by Simon Glass <sjg@chromium.org>
7  *
8  * implementation of SCSI functions required so that CONFIG_SCSI can be enabled
9  * for sandbox.
10  */
11
12 #define LOG_CATEGORY UCLASS_SCSI
13
14 #include <common.h>
15 #include <dm.h>
16 #include <log.h>
17 #include <scsi.h>
18 #include <scsi_emul.h>
19
20 int sb_scsi_emul_command(struct scsi_emul_info *info,
21                          const struct scsi_cmd *req, int len)
22 {
23         int ret = 0;
24
25         info->buff_used = 0;
26         log_debug("emul %x\n", *req->cmd);
27         switch (*req->cmd) {
28         case SCSI_INQUIRY: {
29                 struct scsi_inquiry_resp *resp = (void *)info->buff;
30
31                 info->alloc_len = req->cmd[4];
32                 memset(resp, '\0', sizeof(*resp));
33                 resp->data_format = 1;
34                 resp->additional_len = 0x1f;
35                 strncpy(resp->vendor, info->vendor, sizeof(resp->vendor));
36                 strncpy(resp->product, info->product, sizeof(resp->product));
37                 strncpy(resp->revision, "1.0", sizeof(resp->revision));
38                 info->buff_used = sizeof(*resp);
39                 break;
40         }
41         case SCSI_TST_U_RDY:
42                 break;
43         case SCSI_RD_CAPAC: {
44                 struct scsi_read_capacity_resp *resp = (void *)info->buff;
45                 uint blocks;
46
47                 if (info->file_size)
48                         blocks = info->file_size / info->block_size - 1;
49                 else
50                         blocks = 0;
51                 resp->last_block_addr = cpu_to_be32(blocks);
52                 resp->block_len = cpu_to_be32(info->block_size);
53                 info->buff_used = sizeof(*resp);
54                 break;
55         }
56         case SCSI_READ10: {
57                 const struct scsi_read10_req *read_req = (void *)req;
58
59                 info->seek_block = be32_to_cpu(read_req->lba);
60                 info->read_len = be16_to_cpu(read_req->xfer_len);
61                 info->buff_used = info->read_len * info->block_size;
62                 ret = SCSI_EMUL_DO_READ;
63                 break;
64         }
65         default:
66                 debug("Command not supported: %x\n", req->cmd[0]);
67                 ret = -EPROTONOSUPPORT;
68         }
69         if (ret >= 0)
70                 info->phase = info->transfer_len ? SCSIPH_DATA : SCSIPH_STATUS;
71         log_debug("   - done %x: ret=%d\n", *req->cmd, ret);
72
73         return ret;
74 }