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