blob: d1bb926b713a9b36d99d9131ee136d004f71b5e0 [file] [log] [blame]
Simon Glass4d3b00d2022-09-21 16:21:45 +02001// 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
Simon Glass4d3b00d2022-09-21 16:21:45 +020014#include <dm.h>
15#include <log.h>
16#include <scsi.h>
17#include <scsi_emul.h>
18
19int sb_scsi_emul_command(struct scsi_emul_info *info,
20 const struct scsi_cmd *req, int len)
21{
22 int ret = 0;
23
24 info->buff_used = 0;
25 log_debug("emul %x\n", *req->cmd);
26 switch (*req->cmd) {
27 case SCSI_INQUIRY: {
28 struct scsi_inquiry_resp *resp = (void *)info->buff;
29
30 info->alloc_len = req->cmd[4];
31 memset(resp, '\0', sizeof(*resp));
32 resp->data_format = 1;
33 resp->additional_len = 0x1f;
34 strncpy(resp->vendor, info->vendor, sizeof(resp->vendor));
35 strncpy(resp->product, info->product, sizeof(resp->product));
36 strncpy(resp->revision, "1.0", sizeof(resp->revision));
37 info->buff_used = sizeof(*resp);
38 break;
39 }
40 case SCSI_TST_U_RDY:
41 break;
42 case SCSI_RD_CAPAC: {
43 struct scsi_read_capacity_resp *resp = (void *)info->buff;
44 uint blocks;
45
46 if (info->file_size)
47 blocks = info->file_size / info->block_size - 1;
48 else
49 blocks = 0;
50 resp->last_block_addr = cpu_to_be32(blocks);
51 resp->block_len = cpu_to_be32(info->block_size);
52 info->buff_used = sizeof(*resp);
53 break;
54 }
55 case SCSI_READ10: {
56 const struct scsi_read10_req *read_req = (void *)req;
57
58 info->seek_block = be32_to_cpu(read_req->lba);
59 info->read_len = be16_to_cpu(read_req->xfer_len);
60 info->buff_used = info->read_len * info->block_size;
61 ret = SCSI_EMUL_DO_READ;
62 break;
63 }
Simon Glass31b4f9e2022-10-20 18:22:55 -060064 case SCSI_WRITE10: {
65 const struct scsi_write10_req *write_req = (void *)req;
66
67 info->seek_block = be32_to_cpu(write_req->lba);
68 info->write_len = be16_to_cpu(write_req->xfer_len);
69 info->buff_used = info->write_len * info->block_size;
70 ret = SCSI_EMUL_DO_WRITE;
71 break;
72 }
Simon Glass4d3b00d2022-09-21 16:21:45 +020073 default:
74 debug("Command not supported: %x\n", req->cmd[0]);
75 ret = -EPROTONOSUPPORT;
76 }
77 if (ret >= 0)
78 info->phase = info->transfer_len ? SCSIPH_DATA : SCSIPH_STATUS;
79 log_debug(" - done %x: ret=%d\n", *req->cmd, ret);
80
81 return ret;
82}