474 lines
15 KiB
C
474 lines
15 KiB
C
#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 /* SG_PT_WIN32_H */
|