scsi.h 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. // Copyright (C) 2013 Michael McMaster <michael@codesrc.com>
  2. //
  3. // This file is part of SCSI2SD.
  4. //
  5. // SCSI2SD is free software: you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License as published by
  7. // the Free Software Foundation, either version 3 of the License, or
  8. // (at your option) any later version.
  9. //
  10. // SCSI2SD is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. // GNU General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU General Public License
  16. // along with SCSI2SD. If not, see <http://www.gnu.org/licenses/>.
  17. #ifndef SCSI_H
  18. #define SCSI_H
  19. #include "geometry.h"
  20. #include "sense.h"
  21. #include <stdint.h>
  22. typedef enum
  23. {
  24. // internal bits
  25. __scsiphase_msg = 1,
  26. __scsiphase_cd = 2,
  27. __scsiphase_io = 4,
  28. BUS_FREE = -1,
  29. BUS_BUSY = -2,
  30. ARBITRATION = -3,
  31. SELECTION = -4,
  32. RESELECTION = -5,
  33. STATUS = __scsiphase_cd | __scsiphase_io,
  34. COMMAND = __scsiphase_cd,
  35. DATA_IN = __scsiphase_io,
  36. DATA_OUT = 0,
  37. MESSAGE_IN = __scsiphase_msg | __scsiphase_cd | __scsiphase_io,
  38. MESSAGE_OUT = __scsiphase_msg | __scsiphase_cd
  39. } SCSI_PHASE;
  40. typedef enum
  41. {
  42. GOOD = 0,
  43. CHECK_CONDITION = 2,
  44. BUSY = 0x8,
  45. INTERMEDIATE = 0x10,
  46. CONFLICT = 0x18
  47. } SCSI_STATUS;
  48. typedef enum
  49. {
  50. MSG_COMMAND_COMPLETE = 0,
  51. MSG_REJECT = 0x7,
  52. MSG_LINKED_COMMAND_COMPLETE = 0x0A,
  53. MSG_LINKED_COMMAND_COMPLETE_WITH_FLAG = 0x0B
  54. } SCSI_MESSAGE;
  55. typedef enum
  56. {
  57. COMPAT_UNKNOWN,
  58. COMPAT_SCSI1,
  59. // Messages are being used, yet SCSI 2 mode is disabled.
  60. // This impacts interpretation of INQUIRY commands.
  61. COMPAT_SCSI2_DISABLED,
  62. COMPAT_SCSI2
  63. } SCSI_COMPAT_MODE;
  64. // Maximum value for bytes-per-sector.
  65. #ifndef MAX_SECTOR_SIZE
  66. #define MAX_SECTOR_SIZE 8192
  67. #endif
  68. #ifndef MIN_SECTOR_SIZE
  69. #define MIN_SECTOR_SIZE 64
  70. #endif
  71. #ifndef SCSI2SD_BUFFER_SIZE
  72. #define SCSI2SD_BUFFER_SIZE (MAX_SECTOR_SIZE * 8)
  73. #endif
  74. // Shadow parameters, possibly not saved to flash yet.
  75. // Set via Mode Select
  76. typedef struct
  77. {
  78. uint16_t bytesPerSector;
  79. } LiveCfg;
  80. typedef struct
  81. {
  82. uint8_t targetId;
  83. const S2S_TargetCfg* cfg;
  84. LiveCfg liveCfg;
  85. ScsiSense sense;
  86. uint16_t unitAttention; // Set to the sense qualifier key to be returned.
  87. // Only let the reserved initiator talk to us.
  88. // A 3rd party may be sending the RESERVE/RELEASE commands
  89. int reservedId; // 0 -> 7 if reserved. -1 if not reserved.
  90. int reserverId; // 0 -> 7 if reserved. -1 if not reserved.
  91. uint8_t syncOffset;
  92. uint8_t syncPeriod;
  93. uint8_t started; // Controlled by START STOP UNIT
  94. } TargetState;
  95. typedef struct
  96. {
  97. // TODO reduce this buffer size and add a proper cache
  98. // Must be aligned for DMA
  99. // 65536 bytes is the DMA limit
  100. uint8_t data[SCSI2SD_BUFFER_SIZE];
  101. TargetState targets[S2S_MAX_TARGETS];
  102. TargetState* target;
  103. S2S_BoardCfg boardCfg;
  104. // Set to true (1) if the ATN flag was set, and we need to
  105. // enter the MESSAGE_OUT phase.
  106. int atnFlag;
  107. // Set to true (1) if the RST flag was set.
  108. volatile int resetFlag;
  109. // Set to sel register if the SEL flag was set.
  110. volatile int selFlag;
  111. // Set to true (1) if a parity error was observed.
  112. int parityError;
  113. int phase;
  114. int dataPtr; // Index into data, reset on [re]selection to savedDataPtr
  115. int savedDataPtr; // Index into data, initially 0.
  116. int dataLen;
  117. uint8_t cdb[12]; // command descriptor block
  118. uint8_t cdbLen; // 6, 10, or 12 byte message.
  119. int8_t lun; // Target lun, set by IDENTIFY message.
  120. uint8_t discPriv; // Disconnect priviledge.
  121. uint8_t compatMode; // SCSI_COMPAT_MODE
  122. // Only let the reserved initiator talk to us.
  123. // A 3rd party may be sending the RESERVE/RELEASE commands
  124. int initiatorId; // 0 -> 7. Set during the selection phase.
  125. // SCSI_STATUS value.
  126. // Change to CHECK_CONDITION when setting a SENSE value
  127. uint8_t status;
  128. uint8_t msgIn;
  129. uint8_t msgOut;
  130. void (*postDataOutHook)(void);
  131. uint8_t cmdCount;
  132. uint8_t selCount;
  133. uint8_t rstCount;
  134. uint8_t msgCount;
  135. uint8_t watchdogTick;
  136. uint8_t lastStatus;
  137. uint8_t lastSense;
  138. uint16_t lastSenseASC;
  139. uint8_t minSyncPeriod; // Debug use only.
  140. int needSyncNegotiationAck;
  141. int sdUnderrunCount;
  142. // Estimate of the SCSI host actual speed
  143. uint32_t hostSpeedKBs;
  144. int hostSpeedMeasured;
  145. } ScsiDevice;
  146. extern ScsiDevice scsiDev;
  147. void process_Status(void);
  148. int process_MessageIn(int releaseBusFree);
  149. void enter_BusFree(void);
  150. void scsiInit(void);
  151. void scsiPoll(void);
  152. void scsiDisconnect(void);
  153. int scsiReconnect(void);
  154. // Utility macros, consistent with the Linux Kernel code.
  155. #define likely(x) __builtin_expect(!!(x), 1)
  156. #define unlikely(x) __builtin_expect(!!(x), 0)
  157. //#define likely(x) (x)
  158. //#define unlikely(x) (x)
  159. #endif