xref: /aosp_15_r20/external/sg3_utils/include/sg_pt_nvme.h (revision 44704f698541f6367e81f991ef8bb54ccbf3fc18)
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