1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
|
/*
* nvmecmds.h
*
* Home page of code is: https://www.smartmontools.org
*
* Copyright (C) 2016-23 Christian Franke
*
* Original code from <linux/nvme.h>:
* Copyright (C) 2011-2014 Intel Corporation
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef NVMECMDS_H
#define NVMECMDS_H
#define NVMECMDS_H_CVSID "$Id: nvmecmds.h 5471 2023-05-29 12:22:41Z chrfranke $"
#include "static_assert.h"
#include <errno.h>
#include <stddef.h>
#include <stdint.h>
// The code below was originally imported from <linux/nvme.h> include file from
// Linux kernel sources. Types from <linux/types.h> were replaced.
// Symbol names are unchanged but placed in a namespace to allow inclusion
// of the original <linux/nvme.h>.
namespace smartmontools {
////////////////////////////////////////////////////////////////////////////
// BEGIN: From <linux/nvme.h>
struct nvme_error_log_page {
uint64_t error_count;
unsigned short sqid;
unsigned short cmdid;
unsigned short status_field;
unsigned short parm_error_location;
uint64_t lba;
unsigned int nsid;
unsigned char vs;
unsigned char resv[35];
};
STATIC_ASSERT(sizeof(nvme_error_log_page) == 64);
struct nvme_id_power_state {
unsigned short max_power; // centiwatts
unsigned char rsvd2;
unsigned char flags;
unsigned int entry_lat; // microseconds
unsigned int exit_lat; // microseconds
unsigned char read_tput;
unsigned char read_lat;
unsigned char write_tput;
unsigned char write_lat;
unsigned short idle_power;
unsigned char idle_scale;
unsigned char rsvd19;
unsigned short active_power;
unsigned char active_work_scale;
unsigned char rsvd23[9];
};
STATIC_ASSERT(sizeof(nvme_id_power_state) == 32);
struct nvme_id_ctrl {
unsigned short vid;
unsigned short ssvid;
char sn[20];
char mn[40];
char fr[8];
unsigned char rab;
unsigned char ieee[3];
unsigned char cmic;
unsigned char mdts;
unsigned short cntlid;
unsigned int ver;
unsigned int rtd3r;
unsigned int rtd3e;
unsigned int oaes;
unsigned int ctratt;
unsigned char rsvd100[156];
unsigned short oacs;
unsigned char acl;
unsigned char aerl;
unsigned char frmw;
unsigned char lpa;
unsigned char elpe;
unsigned char npss;
unsigned char avscc;
unsigned char apsta;
unsigned short wctemp;
unsigned short cctemp;
unsigned short mtfa;
unsigned int hmpre;
unsigned int hmmin;
unsigned char tnvmcap[16];
unsigned char unvmcap[16];
unsigned int rpmbs;
unsigned short edstt;
unsigned char dsto;
unsigned char fwug;
unsigned short kas;
unsigned short hctma;
unsigned short mntmt;
unsigned short mxtmt;
unsigned int sanicap;
unsigned char rsvd332[180];
unsigned char sqes;
unsigned char cqes;
unsigned short maxcmd;
unsigned int nn;
unsigned short oncs;
unsigned short fuses;
unsigned char fna;
unsigned char vwc;
unsigned short awun;
unsigned short awupf;
unsigned char nvscc;
unsigned char rsvd531;
unsigned short acwu;
unsigned char rsvd534[2];
unsigned int sgls;
unsigned char rsvd540[228];
char subnqn[256];
unsigned char rsvd1024[768];
unsigned int ioccsz;
unsigned int iorcsz;
unsigned short icdoff;
unsigned char ctrattr;
unsigned char msdbd;
unsigned char rsvd1804[244];
struct nvme_id_power_state psd[32];
unsigned char vs[1024];
};
STATIC_ASSERT(sizeof(nvme_id_ctrl) == 4096);
struct nvme_lbaf {
unsigned short ms;
unsigned char ds;
unsigned char rp;
};
STATIC_ASSERT(sizeof(nvme_lbaf) == 4);
struct nvme_id_ns {
uint64_t nsze;
uint64_t ncap;
uint64_t nuse;
unsigned char nsfeat;
unsigned char nlbaf;
unsigned char flbas;
unsigned char mc;
unsigned char dpc;
unsigned char dps;
unsigned char nmic;
unsigned char rescap;
unsigned char fpi;
unsigned char rsvd33;
unsigned short nawun;
unsigned short nawupf;
unsigned short nacwu;
unsigned short nabsn;
unsigned short nabo;
unsigned short nabspf;
unsigned char rsvd46[2];
unsigned char nvmcap[16];
unsigned char rsvd64[40];
unsigned char nguid[16];
unsigned char eui64[8];
struct nvme_lbaf lbaf[16];
unsigned char rsvd192[192];
unsigned char vs[3712];
};
STATIC_ASSERT(sizeof(nvme_id_ns) == 4096);
struct nvme_smart_log {
unsigned char critical_warning;
unsigned char temperature[2];
unsigned char avail_spare;
unsigned char spare_thresh;
unsigned char percent_used;
unsigned char rsvd6[26];
unsigned char data_units_read[16];
unsigned char data_units_written[16];
unsigned char host_reads[16];
unsigned char host_writes[16];
unsigned char ctrl_busy_time[16];
unsigned char power_cycles[16];
unsigned char power_on_hours[16];
unsigned char unsafe_shutdowns[16];
unsigned char media_errors[16];
unsigned char num_err_log_entries[16];
unsigned int warning_temp_time;
unsigned int critical_comp_time;
unsigned short temp_sensor[8];
unsigned int thm_temp1_trans_count;
unsigned int thm_temp2_trans_count;
unsigned int thm_temp1_total_time;
unsigned int thm_temp2_total_time;
unsigned char rsvd232[280];
};
STATIC_ASSERT(sizeof(nvme_smart_log) == 512);
enum nvme_admin_opcode {
//nvme_admin_delete_sq = 0x00,
//nvme_admin_create_sq = 0x01,
nvme_admin_get_log_page = 0x02,
//nvme_admin_delete_cq = 0x04,
//nvme_admin_create_cq = 0x05,
nvme_admin_identify = 0x06,
//nvme_admin_abort_cmd = 0x08,
//nvme_admin_set_features = 0x09,
//nvme_admin_get_features = 0x0a,
//nvme_admin_async_event = 0x0c,
//nvme_admin_ns_mgmt = 0x0d,
//nvme_admin_activate_fw = 0x10,
//nvme_admin_download_fw = 0x11,
nvme_admin_dev_self_test = 0x14, // NVMe 1.3
//nvme_admin_ns_attach = 0x15,
//nvme_admin_format_nvm = 0x80,
//nvme_admin_security_send = 0x81,
//nvme_admin_security_recv = 0x82,
};
// END: From <linux/nvme.h>
////////////////////////////////////////////////////////////////////////////
// Figure 213 of NVM Express(TM) Base Specification, revision 2.0a, July 2021
struct nvme_self_test_result {
uint8_t self_test_status;
uint8_t segment;
uint8_t valid;
uint8_t rsvd3;
uint8_t power_on_hours[8]; // unaligned LE 64
uint32_t nsid;
uint8_t lba[8]; // unaligned LE 64
uint8_t status_code_type;
uint8_t status_code;
uint8_t vendor_specific[2];
};
STATIC_ASSERT(sizeof(nvme_self_test_result) == 28);
// Figure 212 of NVM Express(TM) Base Specification, revision 2.0a, July 2021
struct nvme_self_test_log {
uint8_t current_operation;
uint8_t current_completion;
uint8_t rsvd2[2];
nvme_self_test_result results[20]; // [0] = newest
};
STATIC_ASSERT(sizeof(nvme_self_test_log) == 564);
} // namespace smartmontools
class nvme_device;
// Print NVMe debug messages?
extern unsigned char nvme_debugmode;
// Read NVMe Identify Controller data structure.
bool nvme_read_id_ctrl(nvme_device * device, smartmontools::nvme_id_ctrl & id_ctrl);
// Read NVMe Identify Namespace data structure for namespace NSID.
bool nvme_read_id_ns(nvme_device * device, unsigned nsid, smartmontools::nvme_id_ns & id_ns);
// Read NVMe log page with identifier LID.
unsigned nvme_read_log_page(nvme_device * device, unsigned nsid, unsigned char lid,
void * data, unsigned size, bool lpo_sup, unsigned offset = 0);
// Read NVMe Error Information Log.
unsigned nvme_read_error_log(nvme_device * device, smartmontools::nvme_error_log_page * error_log,
unsigned num_entries, bool lpo_sup);
// Read NVMe SMART/Health Information log.
bool nvme_read_smart_log(nvme_device * device, smartmontools::nvme_smart_log & smart_log);
// Read NVMe Self-test Log.
bool nvme_read_self_test_log(nvme_device * device, uint32_t nsid,
smartmontools::nvme_self_test_log & self_test_log);
// Start Self-test
bool nvme_self_test(nvme_device * device, uint8_t stc, uint32_t nsid);
// Return true if NVMe status indicates an error.
constexpr bool nvme_status_is_error(uint16_t status)
{ return !!(status & 0x07ff); }
// Return errno for NVMe status SCT/SC fields: 0, EINVAL or EIO.
int nvme_status_to_errno(uint16_t status);
// Return error message for NVMe status SCT/SC fields or nullptr if unknown.
const char * nvme_status_to_str(uint16_t status);
// Return error message for NVMe status SCT/SC fields or explanatory message if unknown.
const char * nvme_status_to_info_str(char * buf, size_t bufsize, uint16_t status);
// Version of above for fixed size buffers.
template <size_t SIZE>
inline const char * nvme_status_to_info_str(char (& buf)[SIZE], unsigned status)
{ return nvme_status_to_info_str(buf, SIZE, status); }
#endif // NVMECMDS_H
|