scsi_emul.c 2.2 KB

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