• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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