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 19 extern "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 26 typedef 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 43 typedef 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 60 typedef 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 69 typedef 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 77 typedef struct { 78 UCHAR NumberOfLogicalUnits; 79 UCHAR InitiatorBusId; 80 ULONG InquiryDataOffset; 81 } SCSI_BUS_DATA, *PSCSI_BUS_DATA; 82 83 84 typedef struct { 85 UCHAR NumberOfBusses; 86 SCSI_BUS_DATA BusData[1]; 87 } SCSI_ADAPTER_BUS_INFO, *PSCSI_ADAPTER_BUS_INFO; 88 89 90 typedef 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 101 typedef 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_ 143 typedef 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 168 typedef enum _STORAGE_PROTOCOL_TYPE { 169 ProtocolTypeUnknown = 0, 170 ProtocolTypeScsi, 171 ProtocolTypeAta, 172 ProtocolTypeNvme, 173 ProtocolTypeSd 174 } STORAGE_PROTOCOL_TYPE; 175 176 typedef enum _STORAGE_PROTOCOL_NVME_DATA_TYPE { 177 NVMeDataTypeUnknown = 0, 178 NVMeDataTypeIdentify, 179 NVMeDataTypeLogPage, 180 NVMeDataTypeFeature 181 } STORAGE_PROTOCOL_NVME_DATA_TYPE; 182 183 typedef 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 195 typedef 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 217 typedef 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 241 typedef 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_ 253 typedef enum _STORAGE_QUERY_TYPE { 254 PropertyStandardQuery = 0, 255 PropertyExistsQuery, 256 PropertyMaskQuery, 257 PropertyQueryMaxDefined 258 } STORAGE_QUERY_TYPE, *PSTORAGE_QUERY_TYPE; 259 260 typedef 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 273 typedef 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 279 typedef 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 // 289 typedef 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 // 304 typedef 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 334 typedef 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 395 typedef 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. */ 419 typedef 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 /* SG_PT_WIN32_H */ 474