spti.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. #include "./spti.h"
  2. #include <ntddscsi.h>
  3. #define CDB6GENERIC_LENGTH 6
  4. #define CDB10GENERIC_LENGTH 10
  5. #define SETBITON 1
  6. #define SETBITOFF 0
  7. //
  8. // Mode Sense/Select page constants.
  9. //
  10. #define MODE_PAGE_ERROR_RECOVERY 0x01
  11. #define MODE_PAGE_DISCONNECT 0x02
  12. #define MODE_PAGE_FORMAT_DEVICE 0x03
  13. #define MODE_PAGE_RIGID_GEOMETRY 0x04
  14. #define MODE_PAGE_FLEXIBILE 0x05
  15. #define MODE_PAGE_VERIFY_ERROR 0x07
  16. #define MODE_PAGE_CACHING 0x08
  17. #define MODE_PAGE_PERIPHERAL 0x09
  18. #define MODE_PAGE_CONTROL 0x0A
  19. #define MODE_PAGE_MEDIUM_TYPES 0x0B
  20. #define MODE_PAGE_NOTCH_PARTITION 0x0C
  21. #define MODE_SENSE_RETURN_ALL 0x3f
  22. #define MODE_SENSE_CURRENT_VALUES 0x00
  23. #define MODE_SENSE_CHANGEABLE_VALUES 0x40
  24. #define MODE_SENSE_DEFAULT_VAULES 0x80
  25. #define MODE_SENSE_SAVED_VALUES 0xc0
  26. #define MODE_PAGE_DEVICE_CONFIG 0x10
  27. #define MODE_PAGE_MEDIUM_PARTITION 0x11
  28. #define MODE_PAGE_DATA_COMPRESS 0x0f
  29. #define MODE_PAGE_CAPABILITIES 0x2A
  30. //
  31. // SCSI CDB operation codes
  32. //
  33. #define SCSIOP_TEST_UNIT_READY 0x00
  34. #define SCSIOP_REZERO_UNIT 0x01
  35. #define SCSIOP_REWIND 0x01
  36. #define SCSIOP_REQUEST_BLOCK_ADDR 0x02
  37. #define SCSIOP_REQUEST_SENSE 0x03
  38. #define SCSIOP_FORMAT_UNIT 0x04
  39. #define SCSIOP_READ_BLOCK_LIMITS 0x05
  40. #define SCSIOP_REASSIGN_BLOCKS 0x07
  41. #define SCSIOP_READ6 0x08
  42. #define SCSIOP_RECEIVE 0x08
  43. #define SCSIOP_WRITE6 0x0A
  44. #define SCSIOP_PRINT 0x0A
  45. #define SCSIOP_SEND 0x0A
  46. #define SCSIOP_SEEK6 0x0B
  47. #define SCSIOP_TRACK_SELECT 0x0B
  48. #define SCSIOP_SLEW_PRINT 0x0B
  49. #define SCSIOP_SEEK_BLOCK 0x0C
  50. #define SCSIOP_PARTITION 0x0D
  51. #define SCSIOP_READ_REVERSE 0x0F
  52. #define SCSIOP_WRITE_FILEMARKS 0x10
  53. #define SCSIOP_FLUSH_BUFFER 0x10
  54. #define SCSIOP_SPACE 0x11
  55. #define SCSIOP_INQUIRY 0x12
  56. #define SCSIOP_VERIFY6 0x13
  57. #define SCSIOP_RECOVER_BUF_DATA 0x14
  58. #define SCSIOP_MODE_SELECT 0x15
  59. #define SCSIOP_RESERVE_UNIT 0x16
  60. #define SCSIOP_RELEASE_UNIT 0x17
  61. #define SCSIOP_COPY 0x18
  62. #define SCSIOP_ERASE 0x19
  63. #define SCSIOP_MODE_SENSE 0x1A
  64. #define SCSIOP_START_STOP_UNIT 0x1B
  65. #define SCSIOP_STOP_PRINT 0x1B
  66. #define SCSIOP_LOAD_UNLOAD 0x1B
  67. #define SCSIOP_RECEIVE_DIAGNOSTIC 0x1C
  68. #define SCSIOP_SEND_DIAGNOSTIC 0x1D
  69. #define SCSIOP_MEDIUM_REMOVAL 0x1E
  70. #define SCSIOP_READ_CAPACITY 0x25
  71. #define SCSIOP_READ 0x28
  72. #define SCSIOP_WRITE 0x2A
  73. #define SCSIOP_SEEK 0x2B
  74. #define SCSIOP_LOCATE 0x2B
  75. #define SCSIOP_WRITE_VERIFY 0x2E
  76. #define SCSIOP_VERIFY 0x2F
  77. #define SCSIOP_SEARCH_DATA_HIGH 0x30
  78. #define SCSIOP_SEARCH_DATA_EQUAL 0x31
  79. #define SCSIOP_SEARCH_DATA_LOW 0x32
  80. #define SCSIOP_SET_LIMITS 0x33
  81. #define SCSIOP_READ_POSITION 0x34
  82. #define SCSIOP_SYNCHRONIZE_CACHE 0x35
  83. #define SCSIOP_COMPARE 0x39
  84. #define SCSIOP_COPY_COMPARE 0x3A
  85. #define SCSIOP_WRITE_DATA_BUFF 0x3B
  86. #define SCSIOP_READ_DATA_BUFF 0x3C
  87. #define SCSIOP_CHANGE_DEFINITION 0x40
  88. #define SCSIOP_READ_SUB_CHANNEL 0x42
  89. #define SCSIOP_READ_TOC 0x43
  90. #define SCSIOP_READ_HEADER 0x44
  91. #define SCSIOP_PLAY_AUDIO 0x45
  92. #define SCSIOP_PLAY_AUDIO_MSF 0x47
  93. #define SCSIOP_PLAY_TRACK_INDEX 0x48
  94. #define SCSIOP_PLAY_TRACK_RELATIVE 0x49
  95. #define SCSIOP_PAUSE_RESUME 0x4B
  96. #define SCSIOP_LOG_SELECT 0x4C
  97. #define SCSIOP_LOG_SENSE 0x4D
  98. #define SCSIOP_READ_DISC_INFORMATION 0x51
  99. typedef struct _SCSI_PASS_THROUGH_WITH_BUFFERS
  100. {
  101. SCSI_PASS_THROUGH spt;
  102. DWORD filler;
  103. UCHAR ucSenseBuf[24];
  104. UCHAR ucDataBuf[256];
  105. }SCSI_PASS_THROUGH_WITH_BUFFERS;
  106. #pragma pack(1)
  107. typedef struct _CDB_START_STOP_UNIT
  108. {
  109. UCHAR OperationCode; // 0x1B - SCSIOP_START_STOP_UNIT
  110. UCHAR Immediate : 1;
  111. UCHAR Reserved1 : 4;
  112. UCHAR Lun : 3;
  113. UCHAR Reserved2[2];
  114. UCHAR Start : 1;
  115. UCHAR LoadEject : 1;
  116. UCHAR Reserved3 : 2;
  117. UCHAR PowerCondition : 4;
  118. UCHAR Control;
  119. } CDB_START_STOP_UNIT;
  120. typedef struct _READ_DISC_INFORMATION
  121. {
  122. UCHAR OperationCode; // 0x51 - SCSIOP_READ_DISC_INFORMATION
  123. UCHAR Reserved1 : 5;
  124. UCHAR Lun : 3;
  125. UCHAR Reserved2[5];
  126. UCHAR AllocationLength[2];
  127. UCHAR Control;
  128. } READ_DISC_INFORMATION;
  129. #pragma pack()
  130. BOOL SPTI_TestUnitReady(HANDLE hDevice, BYTE *pbSC, BYTE *pbASC, BYTE *pbASCQ, INT timeOutSec)
  131. {
  132. INT length;
  133. DWORD returned;
  134. SCSI_PASS_THROUGH_WITH_BUFFERS sptwb;
  135. if (INVALID_HANDLE_VALUE == hDevice) return FALSE;
  136. ZeroMemory(&sptwb, sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS));
  137. sptwb.spt.Length = sizeof(SCSI_PASS_THROUGH);
  138. sptwb.spt.CdbLength = CDB6GENERIC_LENGTH;
  139. sptwb.spt.SenseInfoLength = 24;
  140. sptwb.spt.DataIn = SCSI_IOCTL_DATA_IN;
  141. sptwb.spt.DataTransferLength = 0;
  142. sptwb.spt.TimeOutValue = timeOutSec;
  143. sptwb.spt.DataBufferOffset = ((DWORD)(DWORD_PTR)&sptwb.ucDataBuf) - ((DWORD)(DWORD_PTR)&sptwb);
  144. sptwb.spt.SenseInfoOffset = ((DWORD)(DWORD_PTR)&sptwb.ucSenseBuf) - ((DWORD)(DWORD_PTR)&sptwb);
  145. sptwb.spt.Cdb[0] = SCSIOP_TEST_UNIT_READY;
  146. length = ((DWORD)(DWORD_PTR)&sptwb.ucDataBuf) - ((DWORD)(DWORD_PTR)&sptwb);
  147. DeviceIoControl(hDevice, IOCTL_SCSI_PASS_THROUGH, &sptwb, sizeof(SCSI_PASS_THROUGH), &sptwb, length, &returned, FALSE);
  148. if (pbSC) *pbSC = sptwb.ucSenseBuf[2];
  149. if (pbASC) *pbASC = sptwb.ucSenseBuf[12];
  150. if (pbASCQ) *pbASCQ = sptwb.ucSenseBuf[13];
  151. return TRUE;
  152. }
  153. BOOL SPTI_StartStopUnit(HANDLE hDevice, BOOL bImmediate, BOOL bLoadEject, BOOL bStart, INT timeOutSec, SENSEINFO *pSense)
  154. {
  155. INT length;
  156. BOOL status;
  157. DWORD returned;
  158. CDB_START_STOP_UNIT cmd;
  159. SCSI_PASS_THROUGH_WITH_BUFFERS sptwb;
  160. UNREFERENCED_PARAMETER(pSense);
  161. if (INVALID_HANDLE_VALUE == hDevice) return FALSE;
  162. ZeroMemory(&sptwb, sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS));
  163. ZeroMemory(&cmd, sizeof(CDB_START_STOP_UNIT));
  164. sptwb.spt.Length = sizeof(SCSI_PASS_THROUGH);
  165. sptwb.spt.CdbLength = CDB6GENERIC_LENGTH;
  166. sptwb.spt.SenseInfoLength = 24;
  167. sptwb.spt.DataIn = SCSI_IOCTL_DATA_IN;
  168. sptwb.spt.DataTransferLength = 0;
  169. sptwb.spt.TimeOutValue = timeOutSec;
  170. sptwb.spt.DataBufferOffset = ((DWORD)(DWORD_PTR)&sptwb.ucDataBuf) - ((DWORD)(DWORD_PTR)&sptwb);
  171. sptwb.spt.SenseInfoOffset = ((DWORD)(DWORD_PTR)&sptwb.ucSenseBuf) - ((DWORD)(DWORD_PTR)&sptwb);
  172. cmd.OperationCode = SCSIOP_START_STOP_UNIT;
  173. cmd.Immediate = (bImmediate) ? 1 : 0;
  174. cmd.LoadEject= (bLoadEject) ? 1 : 0;
  175. cmd.Start = (bStart) ? 1 : 0;
  176. CopyMemory(sptwb.spt.Cdb, &cmd, sizeof(CDB_START_STOP_UNIT));
  177. length = ((DWORD)(DWORD_PTR)&sptwb.ucDataBuf) - ((DWORD)(DWORD_PTR)&sptwb);
  178. status = DeviceIoControl(hDevice, IOCTL_SCSI_PASS_THROUGH, &sptwb, sizeof(SCSI_PASS_THROUGH), &sptwb, length, &returned, FALSE);
  179. return status;
  180. }
  181. BOOL SPTI_GetCapabilities(HANDLE hDevice, DWORD *pCap)
  182. {
  183. INT length = 0;
  184. BOOL status;
  185. DWORD returned = 0;
  186. SCSI_PASS_THROUGH_WITH_BUFFERS sptwb;
  187. if (INVALID_HANDLE_VALUE == hDevice || !pCap) return FALSE;
  188. *pCap = 0;
  189. ZeroMemory(&sptwb, sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS));
  190. sptwb.spt.Length = sizeof(SCSI_PASS_THROUGH);
  191. sptwb.spt.CdbLength = CDB6GENERIC_LENGTH;
  192. sptwb.spt.SenseInfoLength = 24;
  193. sptwb.spt.DataIn = SCSI_IOCTL_DATA_IN;
  194. sptwb.spt.DataTransferLength = 192;
  195. sptwb.spt.TimeOutValue = 10; //2 sec
  196. sptwb.spt.DataBufferOffset = ((DWORD)(DWORD_PTR)&sptwb.ucDataBuf) - ((DWORD)(DWORD_PTR)&sptwb);
  197. sptwb.spt.SenseInfoOffset = ((DWORD)(DWORD_PTR)&sptwb.ucSenseBuf) - ((DWORD)(DWORD_PTR)&sptwb);
  198. sptwb.spt.Cdb[0] = SCSIOP_MODE_SENSE;
  199. sptwb.spt.Cdb[1] = 0x08; // target shall not return any block descriptors
  200. sptwb.spt.Cdb[2] = MODE_PAGE_CAPABILITIES;
  201. sptwb.spt.Cdb[4] = 192;
  202. length = ((DWORD)(DWORD_PTR)&sptwb.ucDataBuf) - ((DWORD)(DWORD_PTR)&sptwb) + sptwb.spt.DataTransferLength;;
  203. status = DeviceIoControl(hDevice, IOCTL_SCSI_PASS_THROUGH, &sptwb, sizeof(SCSI_PASS_THROUGH), &sptwb, length, &returned, FALSE);
  204. if (!status) return FALSE;
  205. *pCap = *((DWORD*)&sptwb.ucDataBuf[6]) ;
  206. return TRUE;
  207. }