| #ifndef SG_PT_WIN32_H |
| #define SG_PT_WIN32_H |
| /* |
| * The information in this file was obtained from scsi-wnt.h by |
| * Richard Stemmer, [email protected] . He in turn gives credit to |
| * Jay A. Key (for scsipt.c). |
| * The plscsi program (by Pat LaVarre <[email protected]>) has |
| * also been used as a reference. |
| * Much of the information in this header can also be obtained |
| * from msdn.microsoft.com . |
| * Updated for cygwin version 1.7.17 changes 20121026 |
| */ |
| |
| /* WIN32_LEAN_AND_MEAN may be required to prevent inclusion of <winioctl.h> */ |
| #define WIN32_LEAN_AND_MEAN |
| #include <windows.h> |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| #define SCSI_MAX_SENSE_LEN 64 |
| #define SCSI_MAX_CDB_LEN 16 |
| #define SCSI_MAX_INDIRECT_DATA 16384 |
| |
| typedef struct { |
| USHORT Length; |
| UCHAR ScsiStatus; |
| UCHAR PathId; |
| UCHAR TargetId; |
| UCHAR Lun; |
| UCHAR CdbLength; |
| UCHAR SenseInfoLength; |
| UCHAR DataIn; |
| ULONG DataTransferLength; |
| ULONG TimeOutValue; |
| ULONG_PTR DataBufferOffset; /* was ULONG; problem in 64 bit */ |
| ULONG SenseInfoOffset; |
| UCHAR Cdb[SCSI_MAX_CDB_LEN]; |
| } SCSI_PASS_THROUGH, *PSCSI_PASS_THROUGH; |
| |
| |
| typedef struct { |
| USHORT Length; |
| UCHAR ScsiStatus; |
| UCHAR PathId; |
| UCHAR TargetId; |
| UCHAR Lun; |
| UCHAR CdbLength; |
| UCHAR SenseInfoLength; |
| UCHAR DataIn; |
| ULONG DataTransferLength; |
| ULONG TimeOutValue; |
| PVOID DataBuffer; |
| ULONG SenseInfoOffset; |
| UCHAR Cdb[SCSI_MAX_CDB_LEN]; |
| } SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT; |
| |
| |
| typedef struct { |
| SCSI_PASS_THROUGH spt; |
| /* plscsi shows a follow on 16 bytes allowing 32 byte cdb */ |
| ULONG Filler; |
| UCHAR ucSenseBuf[SCSI_MAX_SENSE_LEN]; |
| UCHAR ucDataBuf[SCSI_MAX_INDIRECT_DATA]; |
| } SCSI_PASS_THROUGH_WITH_BUFFERS, *PSCSI_PASS_THROUGH_WITH_BUFFERS; |
| |
| |
| typedef struct { |
| SCSI_PASS_THROUGH_DIRECT spt; |
| ULONG Filler; |
| UCHAR ucSenseBuf[SCSI_MAX_SENSE_LEN]; |
| } SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, *PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER; |
| |
| |
| |
| typedef struct { |
| UCHAR NumberOfLogicalUnits; |
| UCHAR InitiatorBusId; |
| ULONG InquiryDataOffset; |
| } SCSI_BUS_DATA, *PSCSI_BUS_DATA; |
| |
| |
| typedef struct { |
| UCHAR NumberOfBusses; |
| SCSI_BUS_DATA BusData[1]; |
| } SCSI_ADAPTER_BUS_INFO, *PSCSI_ADAPTER_BUS_INFO; |
| |
| |
| typedef struct { |
| UCHAR PathId; |
| UCHAR TargetId; |
| UCHAR Lun; |
| BOOLEAN DeviceClaimed; |
| ULONG InquiryDataLength; |
| ULONG NextInquiryDataOffset; |
| UCHAR InquiryData[1]; |
| } SCSI_INQUIRY_DATA, *PSCSI_INQUIRY_DATA; |
| |
| |
| typedef struct { |
| ULONG Length; |
| UCHAR PortNumber; |
| UCHAR PathId; |
| UCHAR TargetId; |
| UCHAR Lun; |
| } SCSI_ADDRESS, *PSCSI_ADDRESS; |
| |
| /* |
| * Standard IOCTL define |
| */ |
| #ifndef CTL_CODE |
| #define CTL_CODE(DevType, Function, Method, Access) \ |
| (((DevType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method)) |
| #endif |
| |
| /* |
| * file access values |
| */ |
| #ifndef FILE_ANY_ACCESS |
| #define FILE_ANY_ACCESS 0 |
| #endif |
| #ifndef FILE_READ_ACCESS |
| #define FILE_READ_ACCESS 0x0001 |
| #endif |
| #ifndef FILE_WRITE_ACCESS |
| #define FILE_WRITE_ACCESS 0x0002 |
| #endif |
| |
| // IOCTL_STORAGE_QUERY_PROPERTY |
| |
| #define FILE_DEVICE_MASS_STORAGE 0x0000002d |
| #define IOCTL_STORAGE_BASE FILE_DEVICE_MASS_STORAGE |
| #define FILE_ANY_ACCESS 0 |
| |
| // #define METHOD_BUFFERED 0 |
| |
| #define IOCTL_STORAGE_QUERY_PROPERTY \ |
| CTL_CODE(IOCTL_STORAGE_BASE, 0x0500, METHOD_BUFFERED, FILE_ANY_ACCESS) |
| |
| |
| #ifndef _DEVIOCTL_ |
| typedef enum _STORAGE_BUS_TYPE { |
| BusTypeUnknown = 0x00, |
| BusTypeScsi = 0x01, |
| BusTypeAtapi = 0x02, |
| BusTypeAta = 0x03, |
| BusType1394 = 0x04, |
| BusTypeSsa = 0x05, |
| BusTypeFibre = 0x06, |
| BusTypeUsb = 0x07, |
| BusTypeRAID = 0x08, |
| BusTypeiScsi = 0x09, |
| BusTypeSas = 0x0A, |
| BusTypeSata = 0x0B, |
| BusTypeSd = 0x0C, |
| BusTypeMmc = 0x0D, |
| BusTypeVirtual = 0xE, |
| BusTypeFileBackedVirtual = 0xF, |
| BusTypeSpaces = 0x10, |
| BusTypeNvme = 0x11, |
| BusTypeSCM = 0x12, |
| BusTypeUfs = 0x13, |
| BusTypeMax = 0x14, |
| BusTypeMaxReserved = 0x7F |
| } STORAGE_BUS_TYPE, *PSTORAGE_BUS_TYPE; |
| |
| typedef enum _STORAGE_PROTOCOL_TYPE { |
| ProtocolTypeUnknown = 0, |
| ProtocolTypeScsi, |
| ProtocolTypeAta, |
| ProtocolTypeNvme, |
| ProtocolTypeSd |
| } STORAGE_PROTOCOL_TYPE; |
| |
| typedef enum _STORAGE_PROTOCOL_NVME_DATA_TYPE { |
| NVMeDataTypeUnknown = 0, |
| NVMeDataTypeIdentify, |
| NVMeDataTypeLogPage, |
| NVMeDataTypeFeature |
| } STORAGE_PROTOCOL_NVME_DATA_TYPE; |
| |
| typedef struct _STORAGE_PROTOCOL_SPECIFIC_DATA { |
| STORAGE_PROTOCOL_TYPE ProtocolType; |
| ULONG DataType; |
| ULONG ProtocolDataRequestValue; |
| ULONG ProtocolDataRequestSubValue; |
| ULONG ProtocolDataOffset; |
| ULONG ProtocolDataLength; |
| ULONG FixedProtocolReturnData; |
| ULONG Reserved[3]; |
| } STORAGE_PROTOCOL_SPECIFIC_DATA; |
| |
| |
| typedef struct _STORAGE_DEVICE_DESCRIPTOR { |
| ULONG Version; |
| ULONG Size; |
| UCHAR DeviceType; |
| UCHAR DeviceTypeModifier; |
| BOOLEAN RemovableMedia; |
| BOOLEAN CommandQueueing; |
| ULONG VendorIdOffset; /* 0 if not available */ |
| ULONG ProductIdOffset; /* 0 if not available */ |
| ULONG ProductRevisionOffset;/* 0 if not available */ |
| ULONG SerialNumberOffset; /* -1 if not available ?? */ |
| STORAGE_BUS_TYPE BusType; |
| ULONG RawPropertiesLength; |
| UCHAR RawDeviceProperties[1]; |
| } STORAGE_DEVICE_DESCRIPTOR, *PSTORAGE_DEVICE_DESCRIPTOR; |
| |
| #define STORAGE_PROTOCOL_STRUCTURE_VERSION 0x1 |
| |
| #define IOCTL_STORAGE_PROTOCOL_COMMAND \ |
| CTL_CODE(IOCTL_STORAGE_BASE, 0x04F0, METHOD_BUFFERED, \ |
| FILE_READ_ACCESS | FILE_WRITE_ACCESS) |
| |
| typedef struct _STORAGE_PROTOCOL_COMMAND { |
| DWORD Version; /* STORAGE_PROTOCOL_STRUCTURE_VERSION */ |
| DWORD Length; |
| STORAGE_PROTOCOL_TYPE ProtocolType; |
| DWORD Flags; |
| DWORD ReturnStatus; |
| DWORD ErrorCode; |
| DWORD CommandLength; |
| DWORD ErrorInfoLength; |
| DWORD DataToDeviceTransferLength; |
| DWORD DataFromDeviceTransferLength; |
| DWORD TimeOutValue; |
| DWORD ErrorInfoOffset; |
| DWORD DataToDeviceBufferOffset; |
| DWORD DataFromDeviceBufferOffset; |
| DWORD CommandSpecific; |
| DWORD Reserved0; |
| DWORD FixedProtocolReturnData; |
| DWORD Reserved1[3]; |
| BYTE Command[1]; /* has CommandLength elements */ |
| } STORAGE_PROTOCOL_COMMAND, *PSTORAGE_PROTOCOL_COMMAND; |
| |
| #endif /* _DEVIOCTL_ */ |
| |
| typedef struct _STORAGE_DEVICE_UNIQUE_IDENTIFIER { |
| ULONG Version; |
| ULONG Size; |
| ULONG StorageDeviceIdOffset; |
| ULONG StorageDeviceOffset; |
| ULONG DriveLayoutSignatureOffset; |
| } STORAGE_DEVICE_UNIQUE_IDENTIFIER, *PSTORAGE_DEVICE_UNIQUE_IDENTIFIER; |
| |
| // Use CompareStorageDuids(PSTORAGE_DEVICE_UNIQUE_IDENTIFIER duid1, duid2) |
| // to test for equality |
| |
| #ifndef _DEVIOCTL_ |
| typedef enum _STORAGE_QUERY_TYPE { |
| PropertyStandardQuery = 0, |
| PropertyExistsQuery, |
| PropertyMaskQuery, |
| PropertyQueryMaxDefined |
| } STORAGE_QUERY_TYPE, *PSTORAGE_QUERY_TYPE; |
| |
| typedef enum _STORAGE_PROPERTY_ID { |
| StorageDeviceProperty = 0, |
| StorageAdapterProperty, |
| StorageDeviceIdProperty, |
| StorageDeviceUniqueIdProperty, |
| StorageDeviceWriteCacheProperty, |
| StorageMiniportProperty, |
| StorageAccessAlignmentProperty, |
| /* Identify controller goes to adapter; Identify namespace to device */ |
| StorageAdapterProtocolSpecificProperty = 49, |
| StorageDeviceProtocolSpecificProperty = 50 |
| } STORAGE_PROPERTY_ID, *PSTORAGE_PROPERTY_ID; |
| |
| typedef struct _STORAGE_PROPERTY_QUERY { |
| STORAGE_PROPERTY_ID PropertyId; |
| STORAGE_QUERY_TYPE QueryType; |
| UCHAR AdditionalParameters[1]; |
| } STORAGE_PROPERTY_QUERY, *PSTORAGE_PROPERTY_QUERY; |
| |
| typedef struct _STORAGE_PROTOCOL_DATA_DESCRIPTOR { |
| DWORD Version; |
| DWORD Size; |
| STORAGE_PROTOCOL_SPECIFIC_DATA ProtocolSpecificData; |
| } STORAGE_PROTOCOL_DATA_DESCRIPTOR, *PSTORAGE_PROTOCOL_DATA_DESCRIPTOR; |
| |
| // Command completion status |
| // The "Phase Tag" field and "Status Field" are separated in spec. We define |
| // them in the same data structure to ease the memory access from software. |
| // |
| typedef union { |
| struct { |
| USHORT P : 1; // Phase Tag (P) |
| |
| USHORT SC : 8; // Status Code (SC) |
| USHORT SCT : 3; // Status Code Type (SCT) |
| USHORT Reserved : 2; |
| USHORT M : 1; // More (M) |
| USHORT DNR : 1; // Do Not Retry (DNR) |
| } DUMMYSTRUCTNAME; |
| USHORT AsUshort; |
| } NVME_COMMAND_STATUS, *PNVME_COMMAND_STATUS; |
| |
| // Information of log: NVME_LOG_PAGE_ERROR_INFO. Size: 64 bytes |
| // |
| typedef struct { |
| ULONGLONG ErrorCount; |
| USHORT SQID; // Submission Queue ID |
| USHORT CMDID; // Command ID |
| NVME_COMMAND_STATUS Status; // Status Field: This field indicates the |
| // Status Field for the command that |
| // completed. The Status Field is located in |
| // bits 15:01, bit 00 corresponds to the Phase |
| // Tag posted for the command. |
| struct { |
| USHORT Byte : 8; // Byte in command that contained error |
| USHORT Bit : 3; // Bit in command that contained error |
| USHORT Reserved : 5; |
| } ParameterErrorLocation; |
| |
| ULONGLONG Lba; // LBA: This field indicates the first LBA |
| // that experienced the error condition, if |
| // applicable. |
| ULONG NameSpace; // Namespace: This field indicates the nsid |
| // that the error is associated with, if |
| // applicable. |
| UCHAR VendorInfoAvailable; // Vendor Specific Information Available |
| UCHAR Reserved0[3]; |
| ULONGLONG CommandSpecificInfo; // This field contains command specific |
| // information. If used, the command |
| // definition specifies the information |
| // returned. |
| UCHAR Reserved1[24]; |
| } NVME_ERROR_INFO_LOG, *PNVME_ERROR_INFO_LOG; |
| |
| typedef struct { |
| |
| ULONG DW0; |
| ULONG Reserved; |
| |
| union { |
| struct { |
| USHORT SQHD; // SQ Head Pointer (SQHD) |
| USHORT SQID; // SQ Identifier (SQID) |
| } DUMMYSTRUCTNAME; |
| |
| ULONG AsUlong; |
| } DW2; |
| |
| union { |
| struct { |
| USHORT CID; // Command Identifier (CID) |
| NVME_COMMAND_STATUS Status; |
| } DUMMYSTRUCTNAME; |
| |
| ULONG AsUlong; |
| } DW3; |
| |
| } NVME_COMPLETION_ENTRY, *PNVME_COMPLETION_ENTRY; |
| |
| |
| // Bit-mask values for STORAGE_PROTOCOL_COMMAND - "Flags" field. |
| // |
| // Flag indicates the request targeting to adapter instead of device. |
| #define STORAGE_PROTOCOL_COMMAND_FLAG_ADAPTER_REQUEST 0x80000000 |
| |
| // |
| // Status values for STORAGE_PROTOCOL_COMMAND - "ReturnStatus" field. |
| // |
| #define STORAGE_PROTOCOL_STATUS_PENDING 0x0 |
| #define STORAGE_PROTOCOL_STATUS_SUCCESS 0x1 |
| #define STORAGE_PROTOCOL_STATUS_ERROR 0x2 |
| #define STORAGE_PROTOCOL_STATUS_INVALID_REQUEST 0x3 |
| #define STORAGE_PROTOCOL_STATUS_NO_DEVICE 0x4 |
| #define STORAGE_PROTOCOL_STATUS_BUSY 0x5 |
| #define STORAGE_PROTOCOL_STATUS_DATA_OVERRUN 0x6 |
| #define STORAGE_PROTOCOL_STATUS_INSUFFICIENT_RESOURCES 0x7 |
| |
| #define STORAGE_PROTOCOL_STATUS_NOT_SUPPORTED 0xFF |
| |
| // Command Length for Storage Protocols. |
| // |
| // NVMe commands are always 64 bytes. |
| #define STORAGE_PROTOCOL_COMMAND_LENGTH_NVME 0x40 |
| |
| // Command Specific Information for Storage Protocols - CommandSpecific field |
| // |
| #define STORAGE_PROTOCOL_SPECIFIC_NVME_ADMIN_COMMAND 0x01 |
| #define STORAGE_PROTOCOL_SPECIFIC_NVME_NVM_COMMAND 0x02 |
| |
| #endif /* _DEVIOCTL_ */ |
| |
| |
| // NVME_PASS_THROUGH |
| |
| #ifndef STB_IO_CONTROL |
| typedef struct _SRB_IO_CONTROL { |
| ULONG HeaderLength; |
| UCHAR Signature[8]; |
| ULONG Timeout; |
| ULONG ControlCode; |
| ULONG ReturnCode; |
| ULONG Length; |
| } SRB_IO_CONTROL, *PSRB_IO_CONTROL; |
| #endif |
| |
| #ifndef NVME_PASS_THROUGH_SRB_IO_CODE |
| |
| #define NVME_SIG_STR "NvmeMini" |
| #define NVME_STORPORT_DRIVER 0xe000 |
| |
| #define NVME_PASS_THROUGH_SRB_IO_CODE \ |
| CTL_CODE(NVME_STORPORT_DRIVER, 0x0800, METHOD_BUFFERED, FILE_ANY_ACCESS) |
| |
| #pragma pack(1) |
| |
| /* Following is pre-Win10; used with DeviceIoControl(IOCTL_SCSI_MINIPORT), |
| * in Win10 need DeviceIoControl(IOCTL_STORAGE_PROTOCOL_COMMAND) for pure |
| * pass-through. Win10 also has "Protocol specific queries" for things like |
| * Identify and Get feature. */ |
| typedef struct _NVME_PASS_THROUGH_IOCTL |
| { |
| SRB_IO_CONTROL SrbIoCtrl; |
| ULONG VendorSpecific[6]; |
| ULONG NVMeCmd[16]; /* Command DW[0...15] */ |
| ULONG CplEntry[4]; /* Completion DW[0...3] */ |
| ULONG Direction; /* 0=None, 1=Out, 2=In, 3=I/O */ |
| ULONG QueueId; /* 0=AdminQ */ |
| ULONG DataBufferLen; /* sizeof(DataBuffer) if Data In */ |
| ULONG MetaDataLen; |
| ULONG ReturnBufferLen; /* offsetof(DataBuffer), plus |
| * sizeof(DataBuffer) if Data Out */ |
| UCHAR DataBuffer[1]; |
| } NVME_PASS_THROUGH_IOCTL; |
| #pragma pack() |
| |
| #endif // NVME_PASS_THROUGH_SRB_IO_CODE |
| |
| |
| /* |
| * method codes |
| */ |
| #define METHOD_BUFFERED 0 |
| #define METHOD_IN_DIRECT 1 |
| #define METHOD_OUT_DIRECT 2 |
| #define METHOD_NEITHER 3 |
| |
| |
| #define IOCTL_SCSI_BASE 0x00000004 |
| |
| /* |
| * constants for DataIn member of SCSI_PASS_THROUGH* structures |
| */ |
| #define SCSI_IOCTL_DATA_OUT 0 |
| #define SCSI_IOCTL_DATA_IN 1 |
| #define SCSI_IOCTL_DATA_UNSPECIFIED 2 |
| |
| #define IOCTL_SCSI_PASS_THROUGH CTL_CODE(IOCTL_SCSI_BASE, 0x0401, \ |
| METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) |
| #define IOCTL_SCSI_MINIPORT CTL_CODE(IOCTL_SCSI_BASE, 0x0402, \ |
| METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) |
| #define IOCTL_SCSI_GET_INQUIRY_DATA CTL_CODE(IOCTL_SCSI_BASE, 0x0403, \ |
| METHOD_BUFFERED, FILE_ANY_ACCESS) |
| #define IOCTL_SCSI_GET_CAPABILITIES CTL_CODE(IOCTL_SCSI_BASE, 0x0404, \ |
| METHOD_BUFFERED, FILE_ANY_ACCESS) |
| #define IOCTL_SCSI_PASS_THROUGH_DIRECT CTL_CODE(IOCTL_SCSI_BASE, 0x0405, \ |
| METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) |
| #define IOCTL_SCSI_GET_ADDRESS CTL_CODE(IOCTL_SCSI_BASE, 0x0406, \ |
| METHOD_BUFFERED, FILE_ANY_ACCESS) |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif /* SG_PT_WIN32_H */ |