ZuluSCSI_initiator.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /*
  2. * ZuluSCSI
  3. * Copyright (c) 2022 Rabbit Hole Computing
  4. *
  5. * Main program for initiator mode.
  6. */
  7. #include "ZuluSCSI_config.h"
  8. #include "ZuluSCSI_log.h"
  9. #include "ZuluSCSI_log_trace.h"
  10. #include "ZuluSCSI_initiator.h"
  11. #include <ZuluSCSI_platform.h>
  12. #include <scsi2sd.h>
  13. extern "C" {
  14. #include <scsi.h>
  15. }
  16. #ifndef PLATFORM_HAS_INITIATOR_MODE
  17. void scsiInitiatorInit()
  18. {
  19. }
  20. void scsiInitiatorMainLoop()
  21. {
  22. }
  23. int scsiInitiatorRunCommand(const uint8_t *command, size_t cmdlen,
  24. uint8_t *bufIn, size_t bufInLen,
  25. const uint8_t *bufOut, size_t bufOutLen)
  26. {
  27. return -1;
  28. }
  29. bool scsiInitiatorReadCapacity(int target_id, uint32_t *sectorcount, uint32_t *sectorsize)
  30. {
  31. return false;
  32. }
  33. #else
  34. /*************************************
  35. * High level initiator mode logic *
  36. *************************************/
  37. static uint32_t g_initiator_drives_imaged;
  38. static int g_initiator_next_id;
  39. // Initialization of initiator mode
  40. void scsiInitiatorInit()
  41. {
  42. scsiHostPhyReset();
  43. g_initiator_drives_imaged = 0;
  44. g_initiator_next_id = 0;
  45. }
  46. // High level logic of the initiator mode
  47. void scsiInitiatorMainLoop()
  48. {
  49. // Scan for SCSI drives one at a time
  50. g_initiator_next_id = (g_initiator_next_id + 1) % 8;
  51. uint32_t sectorcount, sectorsize;
  52. if (scsiInitiatorReadCapacity(g_initiator_next_id, &sectorcount, &sectorsize))
  53. {
  54. azlog("SCSI id ", g_initiator_next_id, " capacity ", (int)sectorcount, " sectors x ", (int)sectorsize, " bytes");
  55. }
  56. delay(1000);
  57. }
  58. /*************************************
  59. * Low level command implementations *
  60. *************************************/
  61. int scsiInitiatorRunCommand(int target_id,
  62. const uint8_t *command, size_t cmdLen,
  63. uint8_t *bufIn, size_t bufInLen,
  64. const uint8_t *bufOut, size_t bufOutLen)
  65. {
  66. if (!scsiHostPhySelect(target_id))
  67. {
  68. azdbg("------ Target ", target_id, " did not respond");
  69. scsiHostPhyRelease();
  70. return -1;
  71. }
  72. SCSI_PHASE phase;
  73. int status = -1;
  74. while ((phase = (SCSI_PHASE)scsiHostPhyGetPhase()) != BUS_FREE)
  75. {
  76. if (!scsiHostRequestWaiting())
  77. {
  78. // Wait for target to assert REQ before dealing with the new phase.
  79. // This way we don't react to any spurious status signal changes.
  80. }
  81. else if (phase == MESSAGE_IN)
  82. {
  83. uint8_t dummy = 0;
  84. scsiHostRead(&dummy, 1);
  85. }
  86. else if (phase == MESSAGE_OUT)
  87. {
  88. uint8_t identify_msg = 0x80;
  89. scsiHostWrite(&identify_msg, 1);
  90. }
  91. else if (phase == COMMAND)
  92. {
  93. scsiHostWrite(command, cmdLen);
  94. }
  95. else if (phase == DATA_IN)
  96. {
  97. scsiHostRead(bufIn, bufInLen);
  98. }
  99. else if (phase == DATA_OUT)
  100. {
  101. scsiHostWrite(bufOut, bufOutLen);
  102. }
  103. else if (phase == STATUS)
  104. {
  105. uint8_t tmp = 0;
  106. scsiHostRead(&tmp, 1);
  107. status = tmp;
  108. azdbg("------ STATUS: ", tmp);
  109. }
  110. }
  111. return status;
  112. }
  113. bool scsiInitiatorReadCapacity(int target_id, uint32_t *sectorcount, uint32_t *sectorsize)
  114. {
  115. uint8_t command[10] = {0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  116. uint8_t response[8] = {0};
  117. int status = scsiInitiatorRunCommand(target_id,
  118. command, sizeof(command),
  119. response, sizeof(response),
  120. NULL, 0);
  121. if (status == 0)
  122. {
  123. *sectorcount = ((uint32_t)response[0] << 24)
  124. | ((uint32_t)response[1] << 16)
  125. | ((uint32_t)response[2] << 8)
  126. | ((uint32_t)response[3] << 0);
  127. *sectorsize = ((uint32_t)response[4] << 24)
  128. | ((uint32_t)response[5] << 16)
  129. | ((uint32_t)response[6] << 8)
  130. | ((uint32_t)response[7] << 0);
  131. return true;
  132. }
  133. else
  134. {
  135. *sectorcount = *sectorsize = 0;
  136. return false;
  137. }
  138. }
  139. #endif