1 #ifndef SG_PT_NVME_H 2 #define SG_PT_NVME_H 3 4 /* 5 * Copyright (c) 2017-2018 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 11 #include <stdint.h> 12 #include <stdbool.h> 13 14 #ifdef __cplusplus 15 extern "C" { 16 #endif 17 18 /* structures copied and slightly modified from <linux/nvme_ioctl.h> which 19 * is Copyright (c) 2011-2014, Intel Corporation. */ 20 21 22 /* Note that the command input structure is in (packed) "cpu" format. That 23 * means, for example, if the CPU is little endian (most are) then so is the 24 * structure. However what comes out in the data-in buffer (e.g. for the 25 * Admin Identify command response) is almost all little endian following ATA 26 * (but no SCSI and IP which are big endian) and Intel's preference. There 27 * are exceptions, for example the EUI-64 identifiers in the Admin Identify 28 * response are big endian. 29 * 30 * Code online (e.g. nvme-cli at github.com) seems to like packed strcutures, 31 * the author prefers byte offset plus a range of unaligned integer builders 32 * such as those in sg_unaligned.h . 33 */ 34 35 #ifdef __GNUC__ 36 #ifndef __clang__ 37 struct __attribute__((__packed__)) sg_nvme_user_io 38 #else 39 struct sg_nvme_user_io 40 #endif 41 #else 42 struct sg_nvme_user_io 43 #endif 44 { 45 uint8_t opcode; 46 uint8_t flags; 47 uint16_t control; 48 uint16_t nblocks; 49 uint16_t rsvd; 50 uint64_t metadata; 51 uint64_t addr; 52 uint64_t slba; 53 uint32_t dsmgmt; 54 uint32_t reftag; 55 uint16_t apptag; 56 uint16_t appmask; 57 } 58 #ifdef SG_LIB_FREEBSD 59 __packed; 60 #else 61 ; 62 #endif 63 64 /* Using byte offsets and unaligned be/le copies safer than packed 65 * structures. These are for sg_nvme_user_io . */ 66 #define SG_NVME_IO_OPCODE 0 67 #define SG_NVME_IO_FLAGS 1 68 #define SG_NVME_IO_CONTROL 2 69 #define SG_NVME_IO_NBLOCKS 4 70 #define SG_NVME_IO_RSVD 6 71 #define SG_NVME_IO_METADATA 8 72 #define SG_NVME_IO_ADDR 16 73 #define SG_NVME_IO_SLBA 24 74 #define SG_NVME_IO_DSMGMT 32 75 #define SG_NVME_IO_REFTAG 36 76 #define SG_NVME_IO_APPTAG 40 77 #define SG_NVME_IO_APPMASK 42 78 79 #ifdef __GNUC__ 80 #ifndef __clang__ 81 struct __attribute__((__packed__)) sg_nvme_passthru_cmd 82 #else 83 struct sg_nvme_passthru_cmd 84 #endif 85 #else 86 struct sg_nvme_passthru_cmd 87 #endif 88 { 89 uint8_t opcode; 90 uint8_t flags; 91 uint16_t rsvd1; 92 uint32_t nsid; 93 uint32_t cdw2; 94 uint32_t cdw3; 95 uint64_t metadata; 96 uint64_t addr; 97 uint32_t metadata_len; 98 uint32_t data_len; 99 uint32_t cdw10; 100 uint32_t cdw11; 101 uint32_t cdw12; 102 uint32_t cdw13; 103 uint32_t cdw14; 104 uint32_t cdw15; 105 #ifdef SG_LIB_LINUX 106 uint32_t timeout_ms; 107 uint32_t result; /* out: DWord(0) from completion queue */ 108 #endif 109 } 110 #ifdef SG_LIB_FREEBSD 111 __packed; 112 #else 113 ; 114 #endif 115 116 117 /* Using byte offsets and unaligned be/le copies safer than packed 118 * structures. These are for sg_nvme_passthru_cmd . */ 119 #define SG_NVME_PT_OPCODE 0 /* length: 1 byte */ 120 #define SG_NVME_PT_FLAGS 1 /* length: 1 byte */ 121 #define SG_NVME_PT_RSVD1 2 /* length: 2 bytes */ 122 #define SG_NVME_PT_NSID 4 /* length: 4 bytes */ 123 #define SG_NVME_PT_CDW2 8 /* length: 4 bytes */ 124 #define SG_NVME_PT_CDW3 12 /* length: 4 bytes */ 125 #define SG_NVME_PT_METADATA 16 /* length: 8 bytes */ 126 #define SG_NVME_PT_ADDR 24 /* length: 8 bytes */ 127 #define SG_NVME_PT_METADATA_LEN 32 /* length: 4 bytes */ 128 #define SG_NVME_PT_DATA_LEN 36 /* length: 4 bytes */ 129 #define SG_NVME_PT_CDW10 40 /* length: 4 bytes */ 130 #define SG_NVME_PT_CDW11 44 /* length: 4 bytes */ 131 #define SG_NVME_PT_CDW12 48 /* length: 4 bytes */ 132 #define SG_NVME_PT_CDW13 52 /* length: 4 bytes */ 133 #define SG_NVME_PT_CDW14 56 /* length: 4 bytes */ 134 #define SG_NVME_PT_CDW15 60 /* length: 4 bytes */ 135 136 #ifdef SG_LIB_LINUX 137 /* General references state that "all NVMe commands are 64 bytes long". If 138 * so then the following are add-ons by Linux, go to the OS and not the 139 * the NVMe device. */ 140 #define SG_NVME_PT_TIMEOUT_MS 64 /* length: 4 bytes */ 141 #define SG_NVME_PT_RESULT 68 /* length: 4 bytes */ 142 #endif 143 144 /* Byte offset of Result and Status (plus phase bit) in CQ */ 145 #define SG_NVME_PT_CQ_RESULT 0 /* CDW0, length: 4 bytes */ 146 #define SG_NVME_PT_CQ_DW0 0 /* CDW0, length: 4 bytes */ 147 #define SG_NVME_PT_CQ_DW1 4 /* CDW1, length: 4 bytes */ 148 #define SG_NVME_PT_CQ_DW2 8 /* CDW2, length: 4 bytes */ 149 #define SG_NVME_PT_CQ_DW3 12 /* CDW3, length: 4 bytes */ 150 #define SG_NVME_PT_CQ_STATUS_P 14 /* CDW3 31:16, length: 2 bytes */ 151 152 153 /* Valid namespace IDs (nsid_s) range from 1 to 0xfffffffe, leaving: */ 154 #define SG_NVME_BROADCAST_NSID 0xffffffff /* all namespaces */ 155 #define SG_NVME_CTL_NSID 0x0 /* the "controller's" namespace */ 156 157 /* Given the NVMe Identify Controller response and optionally the NVMe 158 * Identify Namespace response (NULL otherwise), generate the SCSI VPD 159 * page 0x83 (device identification) descriptor(s) in dop. Return the 160 * number of bytes written which will not exceed max_do_len. Probably use 161 * Peripheral Device Type (pdt) of 0 (disk) for don't know. Transport 162 * protocol (tproto) should be -1 if not known, else SCSI value. 163 * N.B. Does not write total VPD page length into dop[2:3] . */ 164 int sg_make_vpd_devid_for_nvme(const uint8_t * nvme_id_ctl_p, 165 const uint8_t * nvme_id_ns_p, int pdt, 166 int tproto, uint8_t * dop, int max_do_len); 167 168 #ifdef __cplusplus 169 } 170 #endif 171 172 #endif /* SG_PT_NVME_H */ 173