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