1 #ifndef SG_PT_NVME_H 2 #define SG_PT_NVME_H 3 4 /* 5 * Copyright (c) 2017-2019 Douglas Gilbert. 6 * All rights reserved. 7 * Use of this source code is governed by a BSD-style 8 * license that can be found in the BSD_LICENSE file. 9 * 10 * SPDX-License-Identifier: BSD-2-Clause 11 */ 12 13 #include <stdint.h> 14 #include <stdbool.h> 15 16 #ifdef __cplusplus 17 extern "C" { 18 #endif 19 20 /* structures copied and slightly modified from <linux/nvme_ioctl.h> which 21 * is Copyright (c) 2011-2014, Intel Corporation. */ 22 23 24 /* Note that the command input structure is in (packed) "cpu" format. That 25 * means, for example, if the CPU is little endian (most are) then so is the 26 * structure. However what comes out in the data-in buffer (e.g. for the 27 * Admin Identify command response) is almost all little endian following ATA 28 * (but no SCSI and IP which are big endian) and Intel's preference. There 29 * are exceptions, for example the EUI-64 identifiers in the Admin Identify 30 * response are big endian. 31 * 32 * Code online (e.g. nvme-cli at github.com) seems to favour packed 33 * structures, while the author prefers byte offset plus a range of unaligned 34 * integer builders such as those in sg_unaligned.h . 35 */ 36 37 #ifdef __GNUC__ 38 #ifndef __clang__ 39 struct __attribute__((__packed__)) sg_nvme_user_io 40 #else 41 struct sg_nvme_user_io 42 #endif 43 #else 44 struct sg_nvme_user_io 45 #endif 46 { 47 uint8_t opcode; 48 uint8_t flags; 49 uint16_t control; 50 uint16_t nblocks; 51 uint16_t rsvd; 52 uint64_t metadata; 53 uint64_t addr; 54 uint64_t slba; 55 uint32_t dsmgmt; 56 uint32_t reftag; 57 uint16_t apptag; 58 uint16_t appmask; 59 } 60 #ifdef SG_LIB_FREEBSD 61 __packed; 62 #else 63 ; 64 #endif 65 66 /* Using byte offsets and unaligned be/le copies safer than packed 67 * structures. These are for sg_nvme_user_io . */ 68 #define SG_NVME_IO_OPCODE 0 69 #define SG_NVME_IO_FLAGS 1 70 #define SG_NVME_IO_CONTROL 2 71 #define SG_NVME_IO_NBLOCKS 4 72 #define SG_NVME_IO_RSVD 6 73 #define SG_NVME_IO_METADATA 8 74 #define SG_NVME_IO_ADDR 16 75 #define SG_NVME_IO_SLBA 24 76 #define SG_NVME_IO_DSMGMT 32 77 #define SG_NVME_IO_REFTAG 36 78 #define SG_NVME_IO_APPTAG 40 79 #define SG_NVME_IO_APPMASK 42 80 81 #ifdef __GNUC__ 82 #ifndef __clang__ 83 struct __attribute__((__packed__)) sg_nvme_passthru_cmd 84 #else 85 struct sg_nvme_passthru_cmd 86 #endif 87 #else 88 struct sg_nvme_passthru_cmd 89 #endif 90 { 91 uint8_t opcode; 92 uint8_t flags; 93 uint16_t rsvd1; 94 uint32_t nsid; 95 uint32_t cdw2; 96 uint32_t cdw3; 97 uint64_t metadata; 98 uint64_t addr; 99 uint32_t metadata_len; 100 uint32_t data_len; 101 uint32_t cdw10; 102 uint32_t cdw11; 103 uint32_t cdw12; 104 uint32_t cdw13; 105 uint32_t cdw14; 106 uint32_t cdw15; 107 #ifdef SG_LIB_LINUX 108 uint32_t timeout_ms; 109 uint32_t result; /* out: DWord(0) from completion queue */ 110 #endif 111 } 112 #ifdef SG_LIB_FREEBSD 113 __packed; 114 #else 115 ; 116 #endif 117 118 struct sg_sntl_dev_state_t { 119 uint8_t scsi_dsense; 120 uint8_t enclosure_override; /* ENC_OV in sdparm */ 121 uint8_t pdt; /* 6 bit value in INQUIRY response */ 122 uint8_t enc_serv; /* single bit in INQUIRY response */ 123 uint8_t id_ctl253; /* NVMSR field of Identify controller (byte 253) */ 124 bool wce; /* Write Cache Enable (WCE) setting */ 125 bool wce_changed; /* WCE setting has been changed */ 126 }; 127 128 struct sg_sntl_result_t { 129 uint8_t sstatus; 130 uint8_t sk; 131 uint8_t asc; 132 uint8_t ascq; 133 uint8_t in_byte; 134 uint8_t in_bit; /* use 255 for 'no bit position given' */ 135 }; 136 137 struct sg_opcode_info_t { 138 uint8_t opcode; 139 uint16_t sa; /* service action, 0 for none */ 140 uint32_t flags; /* OR-ed set of F_* flags */ 141 uint8_t len_mask[16]; /* len=len_mask[0], then mask for cdb[1]... */ 142 /* ignore cdb bytes after position 15 */ 143 }; 144 145 /* Using byte offsets and unaligned be/le copies safer than packed 146 * structures. These are for sg_nvme_passthru_cmd . */ 147 #define SG_NVME_PT_OPCODE 0 /* length: 1 byte */ 148 #define SG_NVME_PT_FLAGS 1 /* length: 1 byte */ 149 #define SG_NVME_PT_RSVD1 2 /* length: 2 bytes */ 150 #define SG_NVME_PT_NSID 4 /* length: 4 bytes */ 151 #define SG_NVME_PT_CDW2 8 /* length: 4 bytes */ 152 #define SG_NVME_PT_CDW3 12 /* length: 4 bytes */ 153 #define SG_NVME_PT_METADATA 16 /* length: 8 bytes */ 154 #define SG_NVME_PT_ADDR 24 /* length: 8 bytes */ 155 #define SG_NVME_PT_METADATA_LEN 32 /* length: 4 bytes */ 156 #define SG_NVME_PT_DATA_LEN 36 /* length: 4 bytes */ 157 #define SG_NVME_PT_CDW10 40 /* length: 4 bytes */ 158 #define SG_NVME_PT_CDW11 44 /* length: 4 bytes */ 159 #define SG_NVME_PT_CDW12 48 /* length: 4 bytes */ 160 #define SG_NVME_PT_CDW13 52 /* length: 4 bytes */ 161 #define SG_NVME_PT_CDW14 56 /* length: 4 bytes */ 162 #define SG_NVME_PT_CDW15 60 /* length: 4 bytes */ 163 164 #ifdef SG_LIB_LINUX 165 /* General references state that "all NVMe commands are 64 bytes long". If 166 * so then the following are add-ons by Linux, go to the OS and not the 167 * the NVMe device. */ 168 #define SG_NVME_PT_TIMEOUT_MS 64 /* length: 4 bytes */ 169 #define SG_NVME_PT_RESULT 68 /* length: 4 bytes */ 170 #endif 171 172 /* Byte offset of Result and Status (plus phase bit) in CQ */ 173 #define SG_NVME_PT_CQ_RESULT 0 /* CDW0, length: 4 bytes */ 174 #define SG_NVME_PT_CQ_DW0 0 /* CDW0, length: 4 bytes */ 175 #define SG_NVME_PT_CQ_DW1 4 /* CDW1, length: 4 bytes */ 176 #define SG_NVME_PT_CQ_DW2 8 /* CDW2, length: 4 bytes */ 177 #define SG_NVME_PT_CQ_DW3 12 /* CDW3, length: 4 bytes */ 178 #define SG_NVME_PT_CQ_STATUS_P 14 /* CDW3 31:16, length: 2 bytes */ 179 180 181 /* Valid namespace IDs (nsid_s) range from 1 to 0xfffffffe, leaving: */ 182 #define SG_NVME_BROADCAST_NSID 0xffffffff /* all namespaces */ 183 #define SG_NVME_CTL_NSID 0x0 /* the "controller's" namespace */ 184 185 /* Vendor specific (sg3_utils) VPD pages */ 186 #define SG_NVME_VPD_NICR 0xde /* NVME Identify controller response */ 187 188 189 /* Given the NVMe Identify Controller response and optionally the NVMe 190 * Identify Namespace response (NULL otherwise), generate the SCSI VPD 191 * page 0x83 (device identification) descriptor(s) in dop. Return the 192 * number of bytes written which will not exceed max_do_len. Probably use 193 * Peripheral Device Type (pdt) of 0 (disk) for don't know. Transport 194 * protocol (tproto) should be -1 if not known, else SCSI value. 195 * N.B. Does not write total VPD page length into dop[2:3] . */ 196 int sg_make_vpd_devid_for_nvme(const uint8_t * nvme_id_ctl_p, 197 const uint8_t * nvme_id_ns_p, int pdt, 198 int tproto, uint8_t * dop, int max_do_len); 199 200 /* Initialize dev_stat pointed to by dsp */ 201 void sntl_init_dev_stat(struct sg_sntl_dev_state_t * dsp); 202 203 /* Internal function (common to all OSes) to support the SNTL SCSI MODE 204 * SENSE(10) command. Has a vendor specific Unit Attention mpage which 205 * has only one field currently: ENC_OV (enclosure override) */ 206 int sntl_resp_mode_sense10(const struct sg_sntl_dev_state_t * dsp, 207 const uint8_t * cdbp, uint8_t * dip, int mx_di_len, 208 struct sg_sntl_result_t * resp); 209 210 /* Internal function (common to all OSes) to support the SNTL SCSI MODE 211 * SELECT(10) command. */ 212 int sntl_resp_mode_select10(struct sg_sntl_dev_state_t * dsp, 213 const uint8_t * cdbp, const uint8_t * dop, 214 int do_len, struct sg_sntl_result_t * resp); 215 216 /* Returns pointer to array of struct sg_opcode_info_t of SCSI commands 217 * translated to NVMe. */ 218 const struct sg_opcode_info_t * sg_get_opcode_translation(void); 219 220 #ifdef __cplusplus 221 } 222 #endif 223 224 #endif /* SG_PT_NVME_H */ 225