14const char *
nvmecmds_cvsid =
"$Id: nvmecmds.cpp 5630 2024-10-23 17:15:56Z chrfranke $"
33 const unsigned char * p = (
const unsigned char *)
data;
34 const unsigned limit = 4096;
35 unsigned sz = (
size <= limit ?
size : limit);
37 while (sz > 0x10 && !p[sz-1])
41 sz = (sz & ~0x0f) + 0x10;
47 dStrHex((
const uint8_t *)p, sz, 0);
57 pout(
" [NVMe call: opcode=0x%02x, size=0x%04x, nsid=0x%08x, cdw10=0x%08x",
60 pout(
",\n cdw1x=0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x",
69 if (start_usec >= 0) {
71 if (duration_usec > 0)
72 pout(
" [Duration: %.6fs]\n", duration_usec / 1000000.0);
79 memset(id_ctrl.
sn,
'X',
sizeof(id_ctrl.
sn));
84 memset(id_ns.
eui64, 0x00,
sizeof(id_ns.
eui64));
90 pout(
" [NVMe call failed: ");
97 pout(
" [NVMe call succeeded: result=0x%08x", out.
result);
120 unsigned char cns,
void *
data,
unsigned size)
156 for (
int i = 0; i < 32; i++) {
184 for (
int i = 0; i < 16; i++)
192 unsigned char lid,
void *
data,
unsigned size,
unsigned offset = 0)
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);
201 in.
cdw10 = lid | (((
size / 4) - 1) << 16);
209 void *
data,
unsigned size,
bool lpo_sup,
unsigned offset )
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");
232 unsigned num_entries,
bool lpo_sup)
235 num_entries *
sizeof(*error_log), lpo_sup);
237 unsigned read_entries = n /
sizeof(*error_log);
239 for (
unsigned i = 0; i < read_entries; i++) {
240 swapx(&error_log[i].error_count);
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);
262 for (
int i = 0; i < 8; i++)
277 for (
int i = 0; i < 20; i++)
299 uint8_t sc = (uint8_t)status;
300 switch ((status >> 8) & 0x7) {
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";
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";
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";
408 else if (sc < 0xb8)
switch (sc) {
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";
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";
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";
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";
454 case 0x60:
return "Controller Pathing Error";
457 case 0x70:
return "Host Pathing Error";
458 case 0x71:
return "Command Aborted By Host";
486 return (
s && *
s ==
'-' ?
s + 1 :
s);
496 uint8_t sct = (status >> 8) & 0x7, sc = (uint8_t)status;
497 const char * pfx = (sc >= 0xc0 ?
"Vendor Specific " :
"Unknown ");
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;
506 snprintf(buf, bufsize,
"%s%s 0x%02x", pfx,
s, sc);
508 snprintf(buf, bufsize,
"Unknown Status 0x%x/0x%02x", sct, sc);
bool dont_print_serial_number
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.
static bool nvme_read_log_page_1(nvme_device *device, unsigned nsid, unsigned char lid, void *data, unsigned size, unsigned offset=0)
bool nvme_read_self_test_log(nvme_device *device, uint32_t nsid, smartmontools::nvme_self_test_log &self_test_log)
int nvme_status_to_errno(uint16_t status)
bool nvme_read_id_ns(nvme_device *device, unsigned nsid, nvme_id_ns &id_ns)
bool nvme_read_id_ctrl(nvme_device *device, nvme_id_ctrl &id_ctrl)
unsigned char nvme_debugmode
bool nvme_self_test(nvme_device *device, uint8_t stc, uint32_t nsid)
const char * nvme_status_to_str(uint16_t status)
unsigned nvme_read_log_page(nvme_device *device, unsigned nsid, unsigned char lid, void *data, unsigned size, bool lpo_sup, unsigned offset)
unsigned nvme_read_error_log(nvme_device *device, nvme_error_log_page *error_log, unsigned num_entries, bool lpo_sup)
bool nvme_read_smart_log(nvme_device *device, uint32_t nsid, nvme_smart_log &smart_log)
const char * nvmecmds_cvsid
static bool nvme_pass_through(nvme_device *device, const nvme_cmd_in &in, nvme_cmd_out &out)
static bool nvme_read_identify(nvme_device *device, unsigned nsid, unsigned char cns, void *data, unsigned size)
const char * nvme_status_to_info_str(char *buf, size_t bufsize, uint16_t status)
static void debug_hex_dump(const void *data, unsigned size)
static const char * nvme_status_to_flagged_str(uint16_t status)
constexpr bool nvme_status_is_error(uint16_t status)
constexpr uint32_t nvme_broadcast_nsid
void dStrHex(const uint8_t *up, int len, int no_ascii)
void pout(const char *fmt,...)
NVMe pass through input parameters.
unsigned char direction() const
Get I/O direction from opcode.
unsigned char opcode
Opcode (CDW0 07:00)
unsigned size
Size of buffer.
unsigned cdw15
Cmd specific.
unsigned nsid
Namespace ID.
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)
long long get_timer_usec()
Get microseconds since some unspecified starting point.
void swapx(unsigned short *p)