1#ifndef SG_PT_WIN32_H 2#define SG_PT_WIN32_H 3/* 4 * The information in this file was obtained from scsi-wnt.h by 5 * Richard Stemmer, rs@epost.de . He in turn gives credit to 6 * Jay A. Key (for scsipt.c). 7 * The plscsi program (by Pat LaVarre <p.lavarre@ieee.org>) has 8 * also been used as a reference. 9 * Much of the information in this header can also be obtained 10 * from msdn.microsoft.com . 11 * Updated for cygwin version 1.7.17 changes 20121026 12 */ 13 14/* WIN32_LEAN_AND_MEAN may be required to prevent inclusion of <winioctl.h> */ 15#define WIN32_LEAN_AND_MEAN 16#include <windows.h> 17 18#ifdef __cplusplus 19extern "C" { 20#endif 21 22#define SCSI_MAX_SENSE_LEN 64 23#define SCSI_MAX_CDB_LEN 16 24#define SCSI_MAX_INDIRECT_DATA 16384 25 26typedef struct { 27 USHORT Length; 28 UCHAR ScsiStatus; 29 UCHAR PathId; 30 UCHAR TargetId; 31 UCHAR Lun; 32 UCHAR CdbLength; 33 UCHAR SenseInfoLength; 34 UCHAR DataIn; 35 ULONG DataTransferLength; 36 ULONG TimeOutValue; 37 ULONG_PTR DataBufferOffset; /* was ULONG; problem in 64 bit */ 38 ULONG SenseInfoOffset; 39 UCHAR Cdb[SCSI_MAX_CDB_LEN]; 40} SCSI_PASS_THROUGH, *PSCSI_PASS_THROUGH; 41 42 43typedef struct { 44 USHORT Length; 45 UCHAR ScsiStatus; 46 UCHAR PathId; 47 UCHAR TargetId; 48 UCHAR Lun; 49 UCHAR CdbLength; 50 UCHAR SenseInfoLength; 51 UCHAR DataIn; 52 ULONG DataTransferLength; 53 ULONG TimeOutValue; 54 PVOID DataBuffer; 55 ULONG SenseInfoOffset; 56 UCHAR Cdb[SCSI_MAX_CDB_LEN]; 57} SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT; 58 59 60typedef struct { 61 SCSI_PASS_THROUGH spt; 62 /* plscsi shows a follow on 16 bytes allowing 32 byte cdb */ 63 ULONG Filler; 64 UCHAR ucSenseBuf[SCSI_MAX_SENSE_LEN]; 65 UCHAR ucDataBuf[SCSI_MAX_INDIRECT_DATA]; 66} SCSI_PASS_THROUGH_WITH_BUFFERS, *PSCSI_PASS_THROUGH_WITH_BUFFERS; 67 68 69typedef struct { 70 SCSI_PASS_THROUGH_DIRECT spt; 71 ULONG Filler; 72 UCHAR ucSenseBuf[SCSI_MAX_SENSE_LEN]; 73} SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, *PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER; 74 75 76 77typedef struct { 78 UCHAR NumberOfLogicalUnits; 79 UCHAR InitiatorBusId; 80 ULONG InquiryDataOffset; 81} SCSI_BUS_DATA, *PSCSI_BUS_DATA; 82 83 84typedef struct { 85 UCHAR NumberOfBusses; 86 SCSI_BUS_DATA BusData[1]; 87} SCSI_ADAPTER_BUS_INFO, *PSCSI_ADAPTER_BUS_INFO; 88 89 90typedef struct { 91 UCHAR PathId; 92 UCHAR TargetId; 93 UCHAR Lun; 94 BOOLEAN DeviceClaimed; 95 ULONG InquiryDataLength; 96 ULONG NextInquiryDataOffset; 97 UCHAR InquiryData[1]; 98} SCSI_INQUIRY_DATA, *PSCSI_INQUIRY_DATA; 99 100 101typedef struct { 102 ULONG Length; 103 UCHAR PortNumber; 104 UCHAR PathId; 105 UCHAR TargetId; 106 UCHAR Lun; 107} SCSI_ADDRESS, *PSCSI_ADDRESS; 108 109/* 110 * Standard IOCTL define 111 */ 112#ifndef CTL_CODE 113#define CTL_CODE(DevType, Function, Method, Access) \ 114 (((DevType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method)) 115#endif 116 117/* 118 * file access values 119 */ 120#ifndef FILE_ANY_ACCESS 121#define FILE_ANY_ACCESS 0 122#endif 123#ifndef FILE_READ_ACCESS 124#define FILE_READ_ACCESS 0x0001 125#endif 126#ifndef FILE_WRITE_ACCESS 127#define FILE_WRITE_ACCESS 0x0002 128#endif 129 130// IOCTL_STORAGE_QUERY_PROPERTY 131 132#define FILE_DEVICE_MASS_STORAGE 0x0000002d 133#define IOCTL_STORAGE_BASE FILE_DEVICE_MASS_STORAGE 134#define FILE_ANY_ACCESS 0 135 136// #define METHOD_BUFFERED 0 137 138#define IOCTL_STORAGE_QUERY_PROPERTY \ 139 CTL_CODE(IOCTL_STORAGE_BASE, 0x0500, METHOD_BUFFERED, FILE_ANY_ACCESS) 140 141 142#ifndef _DEVIOCTL_ 143typedef enum _STORAGE_BUS_TYPE { 144 BusTypeUnknown = 0x00, 145 BusTypeScsi = 0x01, 146 BusTypeAtapi = 0x02, 147 BusTypeAta = 0x03, 148 BusType1394 = 0x04, 149 BusTypeSsa = 0x05, 150 BusTypeFibre = 0x06, 151 BusTypeUsb = 0x07, 152 BusTypeRAID = 0x08, 153 BusTypeiScsi = 0x09, 154 BusTypeSas = 0x0A, 155 BusTypeSata = 0x0B, 156 BusTypeSd = 0x0C, 157 BusTypeMmc = 0x0D, 158 BusTypeVirtual = 0xE, 159 BusTypeFileBackedVirtual = 0xF, 160 BusTypeSpaces = 0x10, 161 BusTypeNvme = 0x11, 162 BusTypeSCM = 0x12, 163 BusTypeUfs = 0x13, 164 BusTypeMax = 0x14, 165 BusTypeMaxReserved = 0x7F 166} STORAGE_BUS_TYPE, *PSTORAGE_BUS_TYPE; 167 168typedef enum _STORAGE_PROTOCOL_TYPE { 169 ProtocolTypeUnknown = 0, 170 ProtocolTypeScsi, 171 ProtocolTypeAta, 172 ProtocolTypeNvme, 173 ProtocolTypeSd 174} STORAGE_PROTOCOL_TYPE; 175 176typedef enum _STORAGE_PROTOCOL_NVME_DATA_TYPE { 177 NVMeDataTypeUnknown = 0, 178 NVMeDataTypeIdentify, 179 NVMeDataTypeLogPage, 180 NVMeDataTypeFeature 181} STORAGE_PROTOCOL_NVME_DATA_TYPE; 182 183typedef struct _STORAGE_PROTOCOL_SPECIFIC_DATA { 184 STORAGE_PROTOCOL_TYPE ProtocolType; 185 ULONG DataType; 186 ULONG ProtocolDataRequestValue; 187 ULONG ProtocolDataRequestSubValue; 188 ULONG ProtocolDataOffset; 189 ULONG ProtocolDataLength; 190 ULONG FixedProtocolReturnData; 191 ULONG Reserved[3]; 192} STORAGE_PROTOCOL_SPECIFIC_DATA; 193 194 195typedef struct _STORAGE_DEVICE_DESCRIPTOR { 196 ULONG Version; 197 ULONG Size; 198 UCHAR DeviceType; 199 UCHAR DeviceTypeModifier; 200 BOOLEAN RemovableMedia; 201 BOOLEAN CommandQueueing; 202 ULONG VendorIdOffset; /* 0 if not available */ 203 ULONG ProductIdOffset; /* 0 if not available */ 204 ULONG ProductRevisionOffset;/* 0 if not available */ 205 ULONG SerialNumberOffset; /* -1 if not available ?? */ 206 STORAGE_BUS_TYPE BusType; 207 ULONG RawPropertiesLength; 208 UCHAR RawDeviceProperties[1]; 209} STORAGE_DEVICE_DESCRIPTOR, *PSTORAGE_DEVICE_DESCRIPTOR; 210 211#define STORAGE_PROTOCOL_STRUCTURE_VERSION 0x1 212 213#define IOCTL_STORAGE_PROTOCOL_COMMAND \ 214 CTL_CODE(IOCTL_STORAGE_BASE, 0x04F0, METHOD_BUFFERED, \ 215 FILE_READ_ACCESS | FILE_WRITE_ACCESS) 216 217typedef struct _STORAGE_PROTOCOL_COMMAND { 218 DWORD Version; /* STORAGE_PROTOCOL_STRUCTURE_VERSION */ 219 DWORD Length; 220 STORAGE_PROTOCOL_TYPE ProtocolType; 221 DWORD Flags; 222 DWORD ReturnStatus; 223 DWORD ErrorCode; 224 DWORD CommandLength; 225 DWORD ErrorInfoLength; 226 DWORD DataToDeviceTransferLength; 227 DWORD DataFromDeviceTransferLength; 228 DWORD TimeOutValue; 229 DWORD ErrorInfoOffset; 230 DWORD DataToDeviceBufferOffset; 231 DWORD DataFromDeviceBufferOffset; 232 DWORD CommandSpecific; 233 DWORD Reserved0; 234 DWORD FixedProtocolReturnData; 235 DWORD Reserved1[3]; 236 BYTE Command[1]; /* has CommandLength elements */ 237} STORAGE_PROTOCOL_COMMAND, *PSTORAGE_PROTOCOL_COMMAND; 238 239#endif /* _DEVIOCTL_ */ 240 241typedef struct _STORAGE_DEVICE_UNIQUE_IDENTIFIER { 242 ULONG Version; 243 ULONG Size; 244 ULONG StorageDeviceIdOffset; 245 ULONG StorageDeviceOffset; 246 ULONG DriveLayoutSignatureOffset; 247} STORAGE_DEVICE_UNIQUE_IDENTIFIER, *PSTORAGE_DEVICE_UNIQUE_IDENTIFIER; 248 249// Use CompareStorageDuids(PSTORAGE_DEVICE_UNIQUE_IDENTIFIER duid1, duid2) 250// to test for equality 251 252#ifndef _DEVIOCTL_ 253typedef enum _STORAGE_QUERY_TYPE { 254 PropertyStandardQuery = 0, 255 PropertyExistsQuery, 256 PropertyMaskQuery, 257 PropertyQueryMaxDefined 258} STORAGE_QUERY_TYPE, *PSTORAGE_QUERY_TYPE; 259 260typedef enum _STORAGE_PROPERTY_ID { 261 StorageDeviceProperty = 0, 262 StorageAdapterProperty, 263 StorageDeviceIdProperty, 264 StorageDeviceUniqueIdProperty, 265 StorageDeviceWriteCacheProperty, 266 StorageMiniportProperty, 267 StorageAccessAlignmentProperty, 268 /* Identify controller goes to adapter; Identify namespace to device */ 269 StorageAdapterProtocolSpecificProperty = 49, 270 StorageDeviceProtocolSpecificProperty = 50 271} STORAGE_PROPERTY_ID, *PSTORAGE_PROPERTY_ID; 272 273typedef struct _STORAGE_PROPERTY_QUERY { 274 STORAGE_PROPERTY_ID PropertyId; 275 STORAGE_QUERY_TYPE QueryType; 276 UCHAR AdditionalParameters[1]; 277} STORAGE_PROPERTY_QUERY, *PSTORAGE_PROPERTY_QUERY; 278 279typedef struct _STORAGE_PROTOCOL_DATA_DESCRIPTOR { 280 DWORD Version; 281 DWORD Size; 282 STORAGE_PROTOCOL_SPECIFIC_DATA ProtocolSpecificData; 283} STORAGE_PROTOCOL_DATA_DESCRIPTOR, *PSTORAGE_PROTOCOL_DATA_DESCRIPTOR; 284 285// Command completion status 286// The "Phase Tag" field and "Status Field" are separated in spec. We define 287// them in the same data structure to ease the memory access from software. 288// 289typedef union { 290 struct { 291 USHORT P : 1; // Phase Tag (P) 292 293 USHORT SC : 8; // Status Code (SC) 294 USHORT SCT : 3; // Status Code Type (SCT) 295 USHORT Reserved : 2; 296 USHORT M : 1; // More (M) 297 USHORT DNR : 1; // Do Not Retry (DNR) 298 } DUMMYSTRUCTNAME; 299 USHORT AsUshort; 300} NVME_COMMAND_STATUS, *PNVME_COMMAND_STATUS; 301 302// Information of log: NVME_LOG_PAGE_ERROR_INFO. Size: 64 bytes 303// 304typedef struct { 305 ULONGLONG ErrorCount; 306 USHORT SQID; // Submission Queue ID 307 USHORT CMDID; // Command ID 308 NVME_COMMAND_STATUS Status; // Status Field: This field indicates the 309 // Status Field for the command that 310 // completed. The Status Field is located in 311 // bits 15:01, bit 00 corresponds to the Phase 312 // Tag posted for the command. 313 struct { 314 USHORT Byte : 8; // Byte in command that contained error 315 USHORT Bit : 3; // Bit in command that contained error 316 USHORT Reserved : 5; 317 } ParameterErrorLocation; 318 319 ULONGLONG Lba; // LBA: This field indicates the first LBA 320 // that experienced the error condition, if 321 // applicable. 322 ULONG NameSpace; // Namespace: This field indicates the nsid 323 // that the error is associated with, if 324 // applicable. 325 UCHAR VendorInfoAvailable; // Vendor Specific Information Available 326 UCHAR Reserved0[3]; 327 ULONGLONG CommandSpecificInfo; // This field contains command specific 328 // information. If used, the command 329 // definition specifies the information 330 // returned. 331 UCHAR Reserved1[24]; 332} NVME_ERROR_INFO_LOG, *PNVME_ERROR_INFO_LOG; 333 334typedef struct { 335 336 ULONG DW0; 337 ULONG Reserved; 338 339 union { 340 struct { 341 USHORT SQHD; // SQ Head Pointer (SQHD) 342 USHORT SQID; // SQ Identifier (SQID) 343 } DUMMYSTRUCTNAME; 344 345 ULONG AsUlong; 346 } DW2; 347 348 union { 349 struct { 350 USHORT CID; // Command Identifier (CID) 351 NVME_COMMAND_STATUS Status; 352 } DUMMYSTRUCTNAME; 353 354 ULONG AsUlong; 355 } DW3; 356 357} NVME_COMPLETION_ENTRY, *PNVME_COMPLETION_ENTRY; 358 359 360// Bit-mask values for STORAGE_PROTOCOL_COMMAND - "Flags" field. 361// 362// Flag indicates the request targeting to adapter instead of device. 363#define STORAGE_PROTOCOL_COMMAND_FLAG_ADAPTER_REQUEST 0x80000000 364 365// 366// Status values for STORAGE_PROTOCOL_COMMAND - "ReturnStatus" field. 367// 368#define STORAGE_PROTOCOL_STATUS_PENDING 0x0 369#define STORAGE_PROTOCOL_STATUS_SUCCESS 0x1 370#define STORAGE_PROTOCOL_STATUS_ERROR 0x2 371#define STORAGE_PROTOCOL_STATUS_INVALID_REQUEST 0x3 372#define STORAGE_PROTOCOL_STATUS_NO_DEVICE 0x4 373#define STORAGE_PROTOCOL_STATUS_BUSY 0x5 374#define STORAGE_PROTOCOL_STATUS_DATA_OVERRUN 0x6 375#define STORAGE_PROTOCOL_STATUS_INSUFFICIENT_RESOURCES 0x7 376 377#define STORAGE_PROTOCOL_STATUS_NOT_SUPPORTED 0xFF 378 379// Command Length for Storage Protocols. 380// 381// NVMe commands are always 64 bytes. 382#define STORAGE_PROTOCOL_COMMAND_LENGTH_NVME 0x40 383 384// Command Specific Information for Storage Protocols - CommandSpecific field 385// 386#define STORAGE_PROTOCOL_SPECIFIC_NVME_ADMIN_COMMAND 0x01 387#define STORAGE_PROTOCOL_SPECIFIC_NVME_NVM_COMMAND 0x02 388 389#endif /* _DEVIOCTL_ */ 390 391 392// NVME_PASS_THROUGH 393 394#ifndef STB_IO_CONTROL 395typedef struct _SRB_IO_CONTROL { 396 ULONG HeaderLength; 397 UCHAR Signature[8]; 398 ULONG Timeout; 399 ULONG ControlCode; 400 ULONG ReturnCode; 401 ULONG Length; 402} SRB_IO_CONTROL, *PSRB_IO_CONTROL; 403#endif 404 405#ifndef NVME_PASS_THROUGH_SRB_IO_CODE 406 407#define NVME_SIG_STR "NvmeMini" 408#define NVME_STORPORT_DRIVER 0xe000 409 410#define NVME_PASS_THROUGH_SRB_IO_CODE \ 411 CTL_CODE(NVME_STORPORT_DRIVER, 0x0800, METHOD_BUFFERED, FILE_ANY_ACCESS) 412 413#pragma pack(1) 414 415/* Following is pre-Win10; used with DeviceIoControl(IOCTL_SCSI_MINIPORT), 416 * in Win10 need DeviceIoControl(IOCTL_STORAGE_PROTOCOL_COMMAND) for pure 417 * pass-through. Win10 also has "Protocol specific queries" for things like 418 * Identify and Get feature. */ 419typedef struct _NVME_PASS_THROUGH_IOCTL 420{ 421 SRB_IO_CONTROL SrbIoCtrl; 422 ULONG VendorSpecific[6]; 423 ULONG NVMeCmd[16]; /* Command DW[0...15] */ 424 ULONG CplEntry[4]; /* Completion DW[0...3] */ 425 ULONG Direction; /* 0=None, 1=Out, 2=In, 3=I/O */ 426 ULONG QueueId; /* 0=AdminQ */ 427 ULONG DataBufferLen; /* sizeof(DataBuffer) if Data In */ 428 ULONG MetaDataLen; 429 ULONG ReturnBufferLen; /* offsetof(DataBuffer), plus 430 * sizeof(DataBuffer) if Data Out */ 431 UCHAR DataBuffer[1]; 432} NVME_PASS_THROUGH_IOCTL; 433#pragma pack() 434 435#endif // NVME_PASS_THROUGH_SRB_IO_CODE 436 437 438/* 439 * method codes 440 */ 441#define METHOD_BUFFERED 0 442#define METHOD_IN_DIRECT 1 443#define METHOD_OUT_DIRECT 2 444#define METHOD_NEITHER 3 445 446 447#define IOCTL_SCSI_BASE 0x00000004 448 449/* 450 * constants for DataIn member of SCSI_PASS_THROUGH* structures 451 */ 452#define SCSI_IOCTL_DATA_OUT 0 453#define SCSI_IOCTL_DATA_IN 1 454#define SCSI_IOCTL_DATA_UNSPECIFIED 2 455 456#define IOCTL_SCSI_PASS_THROUGH CTL_CODE(IOCTL_SCSI_BASE, 0x0401, \ 457 METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) 458#define IOCTL_SCSI_MINIPORT CTL_CODE(IOCTL_SCSI_BASE, 0x0402, \ 459 METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) 460#define IOCTL_SCSI_GET_INQUIRY_DATA CTL_CODE(IOCTL_SCSI_BASE, 0x0403, \ 461 METHOD_BUFFERED, FILE_ANY_ACCESS) 462#define IOCTL_SCSI_GET_CAPABILITIES CTL_CODE(IOCTL_SCSI_BASE, 0x0404, \ 463 METHOD_BUFFERED, FILE_ANY_ACCESS) 464#define IOCTL_SCSI_PASS_THROUGH_DIRECT CTL_CODE(IOCTL_SCSI_BASE, 0x0405, \ 465 METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) 466#define IOCTL_SCSI_GET_ADDRESS CTL_CODE(IOCTL_SCSI_BASE, 0x0406, \ 467 METHOD_BUFFERED, FILE_ANY_ACCESS) 468 469#ifdef __cplusplus 470} 471#endif 472 473#endif 474