#ifndef SG_PT_WIN32_H
#define SG_PT_WIN32_H
/*
* The information in this file was obtained from scsi-wnt.h by
* Richard Stemmer, rs@epost.de . He in turn gives credit to
* Jay A. Key (for scsipt.c).
* The plscsi program (by Pat LaVarre <p.lavarre@ieee.org>) 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