smartmontools SVN Rev 5599
Utility to control and monitor storage systems with "S.M.A.R.T."
nvmecmds.cpp
Go to the documentation of this file.
1/*
2 * nvmecmds.cpp
3 *
4 * Home page of code is: https://www.smartmontools.org
5 *
6 * Copyright (C) 2016-23 Christian Franke
7 *
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
10
11#include "config.h"
12#include "nvmecmds.h"
13
14const char * nvmecmds_cvsid = "$Id: nvmecmds.cpp 5473 2023-05-30 12:36:57Z chrfranke $"
16
17#include "dev_interface.h"
18#include "atacmds.h" // swapx(), dont_print_serial_number
19#include "scsicmds.h" // dStrHex()
20#include "utility.h"
21
22#include <errno.h>
23
24using namespace smartmontools;
25
26// Print NVMe debug messages?
27unsigned char nvme_debugmode = 0;
28
29// Dump up to 4096 bytes, do not dump trailing zero bytes.
30// TODO: Handle this by new unified function in utility.cpp
31static void debug_hex_dump(const void * data, unsigned size)
32{
33 const unsigned char * p = (const unsigned char *)data;
34 const unsigned limit = 4096; // sizeof(nvme_id_ctrl)
35 unsigned sz = (size <= limit ? size : limit);
36
37 while (sz > 0x10 && !p[sz-1])
38 sz--;
39 if (sz < size) {
40 if (sz & 0x0f)
41 sz = (sz & ~0x0f) + 0x10;
42 sz += 0x10;
43 if (sz > size)
44 sz = size;
45 }
46
47 dStrHex((const uint8_t *)p, sz, 0);
48 if (sz < size)
49 pout(" ...\n");
50}
51
52// Call NVMe pass-through and print debug info if requested.
53static bool nvme_pass_through(nvme_device * device, const nvme_cmd_in & in,
54 nvme_cmd_out & out)
55{
56 if (nvme_debugmode) {
57 pout(" [NVMe call: opcode=0x%02x, size=0x%04x, nsid=0x%08x, cdw10=0x%08x",
58 in.opcode, in.size, in.nsid, in.cdw10);
59 if (in.cdw11 || in.cdw12 || in.cdw13 || in.cdw14 || in.cdw15)
60 pout(",\n cdw1x=0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x",
61 in.cdw11, in.cdw12, in.cdw13, in.cdw14, in.cdw15);
62 pout("]\n");
63 }
64
65 auto start_usec = (nvme_debugmode ? get_timer_usec() : -1);
66
67 bool ok = device->nvme_pass_through(in, out);
68
69 if (start_usec >= 0) {
70 auto duration_usec = get_timer_usec() - start_usec;
71 if (duration_usec > 0)
72 pout(" [Duration: %.6fs]\n", duration_usec / 1000000.0);
73 }
74
76 if (in.cdw10 == 0x01 && in.size >= sizeof(nvme_id_ctrl)) {
77 // Identify controller: Invalidate serial number
78 nvme_id_ctrl & id_ctrl = *reinterpret_cast<nvme_id_ctrl *>(in.buffer);
79 memset(id_ctrl.sn, 'X', sizeof(id_ctrl.sn));
80 }
81 else if (in.cdw10 == 0x00 && in.size >= sizeof(nvme_id_ns)) {
82 // Identify namespace: Invalidate IEEE EUI-64
83 nvme_id_ns & id_ns = *reinterpret_cast<nvme_id_ns *>(in.buffer);
84 memset(id_ns.eui64, 0x00, sizeof(id_ns.eui64));
85 }
86 }
87
88 if (nvme_debugmode) {
89 if (!ok) {
90 pout(" [NVMe call failed: ");
91 if (out.status_valid)
92 pout("NVMe Status=0x%04x", out.status);
93 else
94 pout("%s", device->get_errmsg());
95 }
96 else {
97 pout(" [NVMe call succeeded: result=0x%08x", out.result);
99 pout("\n");
100 debug_hex_dump(in.buffer, in.size);
101 pout(" ");
102 }
103 }
104 pout("]\n");
105 }
106
107 return ok;
108}
109
110// Call NVMe pass-through and print debug info if requested.
111// Version without output parameters.
112static bool nvme_pass_through(nvme_device * device, const nvme_cmd_in & in)
113{
114 nvme_cmd_out out;
115 return nvme_pass_through(device, in, out);
116}
117
118// Read NVMe identify info with controller/namespace field CNS.
119static bool nvme_read_identify(nvme_device * device, unsigned nsid,
120 unsigned char cns, void * data, unsigned size)
121{
122 memset(data, 0, size);
123 nvme_cmd_in in;
125 in.nsid = nsid;
126 in.cdw10 = cns;
127
128 return nvme_pass_through(device, in);
129}
130
131// Read NVMe Identify Controller data structure.
133{
134 if (!nvme_read_identify(device, 0, 0x01, &id_ctrl, sizeof(id_ctrl)))
135 return false;
136
137 if (isbigendian()) {
138 swapx(&id_ctrl.vid);
139 swapx(&id_ctrl.ssvid);
140 swapx(&id_ctrl.cntlid);
141 swapx(&id_ctrl.ver);
142 swapx(&id_ctrl.oacs);
143 swapx(&id_ctrl.wctemp);
144 swapx(&id_ctrl.cctemp);
145 swapx(&id_ctrl.mtfa);
146 swapx(&id_ctrl.hmpre);
147 swapx(&id_ctrl.hmmin);
148 swapx(&id_ctrl.rpmbs);
149 swapx(&id_ctrl.nn);
150 swapx(&id_ctrl.oncs);
151 swapx(&id_ctrl.fuses);
152 swapx(&id_ctrl.awun);
153 swapx(&id_ctrl.awupf);
154 swapx(&id_ctrl.acwu);
155 swapx(&id_ctrl.sgls);
156 for (int i = 0; i < 32; i++) {
157 swapx(&id_ctrl.psd[i].max_power);
158 swapx(&id_ctrl.psd[i].entry_lat);
159 swapx(&id_ctrl.psd[i].exit_lat);
160 swapx(&id_ctrl.psd[i].idle_power);
161 swapx(&id_ctrl.psd[i].active_power);
162 }
163 }
164
165 return true;
166}
167
168// Read NVMe Identify Namespace data structure for namespace NSID.
169bool nvme_read_id_ns(nvme_device * device, unsigned nsid, nvme_id_ns & id_ns)
170{
171 if (!nvme_read_identify(device, nsid, 0x00, &id_ns, sizeof(id_ns)))
172 return false;
173
174 if (isbigendian()) {
175 swapx(&id_ns.nsze);
176 swapx(&id_ns.ncap);
177 swapx(&id_ns.nuse);
178 swapx(&id_ns.nawun);
179 swapx(&id_ns.nawupf);
180 swapx(&id_ns.nacwu);
181 swapx(&id_ns.nabsn);
182 swapx(&id_ns.nabo);
183 swapx(&id_ns.nabspf);
184 for (int i = 0; i < 16; i++)
185 swapx(&id_ns.lbaf[i].ms);
186 }
187
188 return true;
189}
190
191static bool nvme_read_log_page_1(nvme_device * device, unsigned nsid,
192 unsigned char lid, void * data, unsigned size, unsigned offset = 0)
193{
194 if (!(4 <= size && size <= 0x1000 && !(size % 4) && !(offset % 4)))
195 return device->set_err(EINVAL, "Invalid NVMe log size %u or offset %u", size, offset);
196
197 memset(data, 0, size);
198 nvme_cmd_in in;
200 in.nsid = nsid;
201 in.cdw10 = lid | (((size / 4) - 1) << 16);
202 in.cdw12 = offset; // LPOL, NVMe 1.2.1
203
204 return nvme_pass_through(device, in);
205}
206
207// Read NVMe log page with identifier LID.
208unsigned nvme_read_log_page(nvme_device * device, unsigned nsid, unsigned char lid,
209 void * data, unsigned size, bool lpo_sup, unsigned offset /* = 0 */)
210{
211 unsigned n, bs;
212 for (n = 0; n < size; n += bs) {
213 if (!lpo_sup && offset + n > 0) {
214 device->set_err(ENOSYS, "Log Page Offset not supported");
215 break;
216 }
217
218 // Limit transfer size to one page to avoid problems with
219 // limits of NVMe pass-through layer or too low MDTS values.
220 bs = size - n;
221 if (bs > 0x1000)
222 bs = 0x1000;
223 if (!nvme_read_log_page_1(device, nsid, lid, (char *)data + n, bs, offset + n))
224 break;
225 }
226
227 return n;
228}
229
230// Read NVMe Error Information Log.
232 unsigned num_entries, bool lpo_sup)
233{
234 unsigned n = nvme_read_log_page(device, 0xffffffff, 0x01, error_log,
235 num_entries * sizeof(*error_log), lpo_sup);
236
237 unsigned read_entries = n / sizeof(*error_log);
238 if (isbigendian()) {
239 for (unsigned i = 0; i < read_entries; i++) {
240 swapx(&error_log[i].error_count);
241 swapx(&error_log[i].sqid);
242 swapx(&error_log[i].cmdid);
243 swapx(&error_log[i].status_field);
244 swapx(&error_log[i].parm_error_location);
245 swapx(&error_log[i].lba);
246 swapx(&error_log[i].nsid);
247 }
248 }
249
250 return read_entries;
251}
252
253// Read NVMe SMART/Health Information log.
255{
256 if (!nvme_read_log_page_1(device, 0xffffffff, 0x02, &smart_log, sizeof(smart_log)))
257 return false;
258
259 if (isbigendian()) {
260 swapx(&smart_log.warning_temp_time);
261 swapx(&smart_log.critical_comp_time);
262 for (int i = 0; i < 8; i++)
263 swapx(&smart_log.temp_sensor[i]);
264 }
265
266 return true;
267}
268
269// Read NVMe Self-test Log.
271 smartmontools::nvme_self_test_log & self_test_log)
272{
273 if (!nvme_read_log_page_1(device, nsid, 0x06, &self_test_log, sizeof(self_test_log)))
274 return false;
275
276 if (isbigendian()) {
277 for (int i = 0; i < 20; i++)
278 swapx(&self_test_log.results[i].nsid);
279 }
280
281 return true;
282}
283
284// Start Self-test
285bool nvme_self_test(nvme_device * device, uint8_t stc, uint32_t nsid)
286{
287 nvme_cmd_in in;
289 in.nsid = nsid;
290 in.cdw10 = stc;
291 return nvme_pass_through(device, in);
292}
293
294// Return flagged error message for NVMe status SCT/SC fields or nullptr if unknown.
295// If message starts with '-', the status indicates an invalid command (EINVAL).
296static const char * nvme_status_to_flagged_str(uint16_t status)
297{
298 // Section 3.3.3.2.1 of NVM Express Base Specification Revision 2.0c, October 4, 2022
299 uint8_t sc = (uint8_t)status;
300 switch ((status >> 8) & 0x7) {
301 case 0x0: // Generic Command Status
302 if (sc < 0x80) switch (sc) {
303 case 0x00: return "Successful Completion";
304 case 0x01: return "-Invalid Command Opcode";
305 case 0x02: return "-Invalid Field in Command";
306 case 0x03: return "Command ID Conflict";
307 case 0x04: return "Data Transfer Error";
308 case 0x05: return "Commands Aborted due to Power Loss Notification";
309 case 0x06: return "Internal Error";
310 case 0x07: return "Command Abort Requested";
311 case 0x08: return "Command Aborted due to SQ Deletion";
312 case 0x09: return "Command Aborted due to Failed Fused Command";
313 case 0x0a: return "Command Aborted due to Missing Fused Command";
314 case 0x0b: return "-Invalid Namespace or Format";
315 case 0x0c: return "Command Sequence Error";
316 case 0x0d: return "-Invalid SGL Segment Descriptor";
317 case 0x0e: return "-Invalid Number of SGL Descriptors";
318 case 0x0f: return "-Data SGL Length Invalid";
319 case 0x10: return "-Metadata SGL Length Invalid";
320 case 0x11: return "-SGL Descriptor Type Invalid";
321 case 0x12: return "-Invalid Use of Controller Memory Buffer";
322 case 0x13: return "-PRP Offset Invalid";
323 case 0x14: return "Atomic Write Unit Exceeded";
324 case 0x15: return "Operation Denied";
325 case 0x16: return "-SGL Offset Invalid";
326 case 0x18: return "Host Identifier Inconsistent Format";
327 case 0x19: return "Keep Alive Timer Expired";
328 case 0x1a: return "-Keep Alive Timeout Invalid";
329 case 0x1b: return "Command Aborted due to Preempt and Abort";
330 case 0x1c: return "Sanitize Failed";
331 case 0x1d: return "Sanitize In Progress";
332 case 0x1e: return "SGL Data Block Granularity Invalid";
333 case 0x1f: return "Command Not Supported for Queue in CMB";
334 case 0x20: return "Namespace is Write Protected";
335 case 0x21: return "Command Interrupted";
336 case 0x22: return "Transient Transport Error";
337 case 0x23: return "Command Prohibited by Command and Feature Lockdown";
338 case 0x24: return "Admin Command Media Not Ready";
339 // 0x25-0x7f: Reserved
340 }
341 else switch (sc) {
342 // 0x80-0xbf: I/O Command Set Specific
343 case 0x80: return "LBA Out of Range";
344 case 0x81: return "Capacity Exceeded";
345 case 0x82: return "Namespace Not Ready";
346 case 0x83: return "Reservation Conflict";
347 case 0x84: return "Format In Progress";
348 case 0x85: return "-Invalid Value Size";
349 case 0x86: return "-Invalid Key Size";
350 case 0x87: return "KV Key Does Not Exist";
351 case 0x88: return "Unrecovered Error";
352 case 0x89: return "Key Exists";
353 // 0x90-0xbf: Reserved
354 // 0xc0-0xff: Vendor Specific
355 }
356 break;
357
358 case 0x1: // Command Specific Status
359 if (sc < 0x80) switch (sc) {
360 case 0x00: return "-Completion Queue Invalid";
361 case 0x01: return "-Invalid Queue Identifier";
362 case 0x02: return "-Invalid Queue Size";
363 case 0x03: return "Abort Command Limit Exceeded";
364 case 0x04: return "Abort Command Is Missing";
365 case 0x05: return "Asynchronous Event Request Limit Exceeded";
366 case 0x06: return "-Invalid Firmware Slot";
367 case 0x07: return "-Invalid Firmware Image";
368 case 0x08: return "-Invalid Interrupt Vector";
369 case 0x09: return "-Invalid Log Page";
370 case 0x0a: return "-Invalid Format";
371 case 0x0b: return "Firmware Activation Requires Conventional Reset";
372 case 0x0c: return "-Invalid Queue Deletion";
373 case 0x0d: return "Feature Identifier Not Saveable";
374 case 0x0e: return "Feature Not Changeable";
375 case 0x0f: return "Feature Not Namespace Specific";
376 case 0x10: return "Firmware Activation Requires NVM Subsystem Reset";
377 case 0x11: return "Firmware Activation Requires Controller Level Reset";
378 case 0x12: return "Firmware Activation Requires Maximum Time Violation";
379 case 0x13: return "Firmware Activation Prohibited";
380 case 0x14: return "Overlapping Range";
381 case 0x15: return "Namespace Insufficient Capacity";
382 case 0x16: return "-Namespace Identifier Unavailable";
383 case 0x18: return "Namespace Already Attached";
384 case 0x19: return "Namespace Is Private";
385 case 0x1a: return "Namespace Not Attached";
386 case 0x1b: return "Thin Provisioning Not Supported";
387 case 0x1c: return "-Controller List Invalid";
388 case 0x1d: return "Device Self-test In Progress";
389 case 0x1e: return "Boot Partition Write Prohibited";
390 case 0x1f: return "Invalid Controller Identifier";
391 case 0x20: return "-Invalid Secondary Controller State";
392 case 0x21: return "-Invalid Number of Controller Resources";
393 case 0x22: return "-Invalid Resource Identifier";
394 case 0x23: return "Sanitize Prohibited While Persistent Memory Region is Enabled";
395 case 0x24: return "-ANA Group Identifier Invalid";
396 case 0x25: return "ANA Attach Failed";
397 case 0x26: return "Insufficient Capacity";
398 case 0x27: return "Namespace Attachment Limit Exceeded";
399 case 0x28: return "Prohibition of Command Execution Not Supported";
400 case 0x29: return "I/O Command Set Not Supported";
401 case 0x2a: return "I/O Command Set Not Enabled";
402 case 0x2b: return "I/O Command Set Combination Rejected";
403 case 0x2c: return "-Invalid I/O Command Set";
404 case 0x2d: return "-Identifier Unavailable";
405 // 0x2e-0x6f: Reserved
406 // 0x70-0x7f: Directive Specific
407 }
408 else if (sc < 0xb8) switch (sc) {
409 // 0x80-0xbf: I/O Command Set Specific (overlap with Fabrics Command Set)
410 case 0x80: return "-Conflicting Attributes";
411 case 0x81: return "-Invalid Protection Information";
412 case 0x82: return "Attempted Write to Read Only Range";
413 case 0x83: return "Command Size Limit Exceeded";
414 // 0x84-0xb7: Reserved
415 }
416 else switch (sc) {
417 case 0xb8: return "Zoned Boundary Error";
418 case 0xb9: return "Zone Is Full";
419 case 0xba: return "Zone Is Read Only";
420 case 0xbb: return "Zone Is Offline";
421 case 0xbc: return "Zone Invalid Write";
422 case 0xbd: return "Too Many Active Zones";
423 case 0xbe: return "Too Many Open Zones";
424 case 0xbf: return "Invalid Zone State Transition";
425 // 0xc0-0xff: Vendor Specific
426 }
427 break;
428
429 case 0x2: // Media and Data Integrity Errors
430 switch (sc) {
431 // 0x00-0x7f: Reserved
432 case 0x80: return "Write Fault";
433 case 0x81: return "Unrecovered Read Error";
434 case 0x82: return "End-to-end Guard Check Error";
435 case 0x83: return "End-to-end Application Tag Check Error";
436 case 0x84: return "End-to-end Reference Tag Check Error";
437 case 0x85: return "Compare Failure";
438 case 0x86: return "Access Denied";
439 case 0x87: return "Deallocated or Unwritten Logical Block";
440 case 0x88: return "End-to-End Storage Tag Check Error";
441 // 0x89-0xbf: Reserved
442 // 0xc0-0xff: Vendor Specific
443 }
444 break;
445
446 case 0x3: // Path Related Status
447 switch (sc) {
448 case 0x00: return "Internal Path Error";
449 case 0x01: return "Asymmetric Access Persistent Loss";
450 case 0x02: return "Asymmetric Access Inaccessible";
451 case 0x03: return "Asymmetric Access Transition";
452 // 0x04-0x5f: Reserved
453 // 0x60-0x6f: Controller Detected Pathing Errors
454 case 0x60: return "Controller Pathing Error";
455 // 0x61-0x6f: Reserved
456 // 0x70-0x7f: Host Detected Pathing Errors
457 case 0x70: return "Host Pathing Error";
458 case 0x71: return "Command Aborted By Host";
459 // 0x72-0x7f: Reserved
460 // 0x80-0xbf: I/O Command Set Specific
461 // 0xc0-0xff: Vendor Specific
462 }
463 break;
464
465 // 0x4-0x6: Reserved
466 // 0x7: Vendor Specific
467 }
468 return nullptr;
469}
470
471// Return errno for NVMe status SCT/SC fields: 0, EINVAL or EIO.
472int nvme_status_to_errno(uint16_t status)
473{
474 if (!nvme_status_is_error(status))
475 return 0;
476 const char * s = nvme_status_to_flagged_str(status);
477 if (s && *s == '-')
478 return EINVAL;
479 return EIO;
480}
481
482// Return error message for NVMe status SCT/SC fields or nullptr if unknown.
483const char * nvme_status_to_str(uint16_t status)
484{
485 const char * s = nvme_status_to_flagged_str(status);
486 return (s && *s == '-' ? s + 1 : s);
487}
488
489// Return error message for NVMe status SCT/SC fields or explanatory message if unknown.
490const char * nvme_status_to_info_str(char * buf, size_t bufsize, uint16_t status)
491{
492 const char * s = nvme_status_to_str(status);
493 if (s)
494 return s;
495
496 uint8_t sct = (status >> 8) & 0x7, sc = (uint8_t)status;
497 const char * pfx = (sc >= 0xc0 ? "Vendor Specific " : "Unknown ");
498 switch (sct) {
499 case 0x0: s = "Generic Command Status"; break;
500 case 0x1: s = "Command Specific Status"; break;
501 case 0x2: s = "Media and Data Integrity Error"; break;
502 case 0x3: s = "Path Related Status"; break;
503 case 0x7: s = "Vendor Specific Status"; pfx = ""; break;
504 }
505 if (s)
506 snprintf(buf, bufsize, "%s%s 0x%02x", pfx, s, sc);
507 else
508 snprintf(buf, bufsize, "Unknown Status 0x%x/0x%02x", sct, sc);
509 return buf;
510}
bool dont_print_serial_number
Definition: atacmds.cpp:37
NVMe device access.
virtual bool nvme_pass_through(const nvme_cmd_in &in, nvme_cmd_out &out)=0
NVMe pass through.
const char * get_errmsg() const
Get last error message.
bool set_err(int no, const char *msg,...) __attribute_format_printf(3
Set last error number and message.
u16 s[6]
Definition: megaraid.h:18
ptr_t data
Definition: megaraid.h:15
u32 size
Definition: megaraid.h:0
@ nvme_admin_identify
Definition: nvmecmds.h:210
@ nvme_admin_get_log_page
Definition: nvmecmds.h:207
@ nvme_admin_dev_self_test
Definition: nvmecmds.h:218
uint32_t nsid
uint16_t sqid
static bool nvme_read_log_page_1(nvme_device *device, unsigned nsid, unsigned char lid, void *data, unsigned size, unsigned offset=0)
Definition: nvmecmds.cpp:191
bool nvme_read_self_test_log(nvme_device *device, uint32_t nsid, smartmontools::nvme_self_test_log &self_test_log)
Definition: nvmecmds.cpp:270
int nvme_status_to_errno(uint16_t status)
Definition: nvmecmds.cpp:472
bool nvme_read_id_ns(nvme_device *device, unsigned nsid, nvme_id_ns &id_ns)
Definition: nvmecmds.cpp:169
bool nvme_read_id_ctrl(nvme_device *device, nvme_id_ctrl &id_ctrl)
Definition: nvmecmds.cpp:132
unsigned char nvme_debugmode
Definition: nvmecmds.cpp:27
bool nvme_self_test(nvme_device *device, uint8_t stc, uint32_t nsid)
Definition: nvmecmds.cpp:285
const char * nvme_status_to_str(uint16_t status)
Definition: nvmecmds.cpp:483
bool nvme_read_smart_log(nvme_device *device, nvme_smart_log &smart_log)
Definition: nvmecmds.cpp:254
unsigned nvme_read_log_page(nvme_device *device, unsigned nsid, unsigned char lid, void *data, unsigned size, bool lpo_sup, unsigned offset)
Definition: nvmecmds.cpp:208
unsigned nvme_read_error_log(nvme_device *device, nvme_error_log_page *error_log, unsigned num_entries, bool lpo_sup)
Definition: nvmecmds.cpp:231
const char * nvmecmds_cvsid
Definition: nvmecmds.cpp:14
static bool nvme_pass_through(nvme_device *device, const nvme_cmd_in &in, nvme_cmd_out &out)
Definition: nvmecmds.cpp:53
static bool nvme_read_identify(nvme_device *device, unsigned nsid, unsigned char cns, void *data, unsigned size)
Definition: nvmecmds.cpp:119
const char * nvme_status_to_info_str(char *buf, size_t bufsize, uint16_t status)
Definition: nvmecmds.cpp:490
static void debug_hex_dump(const void *data, unsigned size)
Definition: nvmecmds.cpp:31
static const char * nvme_status_to_flagged_str(uint16_t status)
Definition: nvmecmds.cpp:296
constexpr bool nvme_status_is_error(uint16_t status)
Definition: nvmecmds.h:284
#define NVMECMDS_H_CVSID
Definition: nvmecmds.h:17
void dStrHex(const uint8_t *up, int len, int no_ascii)
Definition: scsicmds.cpp:368
void pout(const char *fmt,...)
Definition: smartd.cpp:1338
NVMe pass through input parameters.
unsigned char direction() const
Get I/O direction from opcode.
unsigned cdw10
unsigned cdw13
unsigned cdw11
unsigned char opcode
Opcode (CDW0 07:00)
unsigned size
Size of buffer.
unsigned cdw14
unsigned cdw15
Cmd specific.
unsigned nsid
Namespace ID.
unsigned cdw12
void set_data_in(unsigned char op, void *buf, unsigned sz)
void * buffer
Pointer to data buffer.
NVMe pass through output parameters.
bool status_valid
true if status is valid
unsigned short status
Status Field (DW3 31:17)
unsigned result
Command specific result (DW0)
unsigned short wctemp
Definition: nvmecmds.h:92
unsigned short ssvid
Definition: nvmecmds.h:68
unsigned short cntlid
Definition: nvmecmds.h:76
struct nvme_id_power_state psd[32]
Definition: nvmecmds.h:133
unsigned short fuses
Definition: nvmecmds.h:114
unsigned short mtfa
Definition: nvmecmds.h:94
unsigned short vid
Definition: nvmecmds.h:67
unsigned short oacs
Definition: nvmecmds.h:83
unsigned short awupf
Definition: nvmecmds.h:118
unsigned short cctemp
Definition: nvmecmds.h:93
struct nvme_lbaf lbaf[16]
Definition: nvmecmds.h:170
unsigned short nabspf
Definition: nvmecmds.h:164
unsigned short nacwu
Definition: nvmecmds.h:161
unsigned short nawun
Definition: nvmecmds.h:159
unsigned short nabo
Definition: nvmecmds.h:163
unsigned short nabsn
Definition: nvmecmds.h:162
unsigned short nawupf
Definition: nvmecmds.h:160
unsigned char eui64[8]
Definition: nvmecmds.h:169
unsigned short ms
Definition: nvmecmds.h:139
nvme_self_test_result results[20]
Definition: nvmecmds.h:248
unsigned int critical_comp_time
Definition: nvmecmds.h:194
unsigned short temp_sensor[8]
Definition: nvmecmds.h:195
unsigned int warning_temp_time
Definition: nvmecmds.h:193
long long get_timer_usec()
Get microseconds since some unspecified starting point.
Definition: utility.cpp:865
bool isbigendian()
Definition: utility.h:82
void swapx(unsigned short *p)
Definition: utility.h:95