From 1d583b7856dba94db75b67d632d0ccda7a3dbddf Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Wed, 31 May 2023 20:52:09 +0200 Subject: [PATCH] nvme-print-stdout: Refactor stdout print code to use print_ops Use the newly introduced print_ops infrastructure to for the stdout printing code. Signed-off-by: Daniel Wagner --- meson.build | 1 + nvme-print-stdout.c | 4804 +++++++++++++++++++++++++++++++++++++++++++ nvme-print.c | 4667 ++--------------------------------------- nvme-print.h | 2 + 4 files changed, 4931 insertions(+), 4543 deletions(-) create mode 100644 nvme-print-stdout.c diff --git a/meson.build b/meson.build index 7ec357a9..2d0c7673 100644 --- a/meson.build +++ b/meson.build @@ -245,6 +245,7 @@ sources = [ 'nvme.c', 'nvme-models.c', 'nvme-print.c', + 'nvme-print-stdout.c', 'nvme-rpmb.c', 'nvme-wrap.c', 'plugin.c', diff --git a/nvme-print-stdout.c b/nvme-print-stdout.c new file mode 100644 index 00000000..65e48afb --- /dev/null +++ b/nvme-print-stdout.c @@ -0,0 +1,4804 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#include +#include +#include +#include +#include +#include +#include + +#include "nvme.h" +#include "libnvme.h" +#include "nvme-print.h" +#include "nvme-models.h" +#include "util/suffix.h" +#include "util/types.h" +#include "common.h" + +static const uint8_t zero_uuid[16] = { 0 }; +static const uint8_t invalid_uuid[16] = {[0 ... 15] = 0xff }; +static const char dash[100] = {[0 ... 99] = '-'}; + +static struct print_ops stdout_print_ops; + +struct nvme_bar_cap { + __u16 mqes; + __u8 ams_cqr; + __u8 to; + __u16 bps_css_nssrs_dstrd; + __u8 mpsmax_mpsmin; + __u8 rsvd_crms_nsss_cmbs_pmrs; +}; + +static void stdout_feature_show_fields(enum nvme_features_id fid, + unsigned int result, + unsigned char *buf); +static void stdout_smart_log(struct nvme_smart_log *smart, + unsigned int nsid, + const char *devname); + +static void stdout_predictable_latency_per_nvmset( + struct nvme_nvmset_predictable_lat_log *plpns_log, + __u16 nvmset_id, const char *devname) +{ + printf("Predictable Latency Per NVM Set Log for device: %s\n", + devname); + printf("Predictable Latency Per NVM Set Log for NVM Set ID: %u\n", + le16_to_cpu(nvmset_id)); + printf("Status: %u\n", plpns_log->status); + printf("Event Type: %u\n", + le16_to_cpu(plpns_log->event_type)); + printf("DTWIN Reads Typical: %"PRIu64"\n", + le64_to_cpu(plpns_log->dtwin_rt)); + printf("DTWIN Writes Typical: %"PRIu64"\n", + le64_to_cpu(plpns_log->dtwin_wt)); + printf("DTWIN Time Maximum: %"PRIu64"\n", + le64_to_cpu(plpns_log->dtwin_tmax)); + printf("NDWIN Time Minimum High: %"PRIu64" \n", + le64_to_cpu(plpns_log->ndwin_tmin_hi)); + printf("NDWIN Time Minimum Low: %"PRIu64"\n", + le64_to_cpu(plpns_log->ndwin_tmin_lo)); + printf("DTWIN Reads Estimate: %"PRIu64"\n", + le64_to_cpu(plpns_log->dtwin_re)); + printf("DTWIN Writes Estimate: %"PRIu64"\n", + le64_to_cpu(plpns_log->dtwin_we)); + printf("DTWIN Time Estimate: %"PRIu64"\n\n\n", + le64_to_cpu(plpns_log->dtwin_te)); +} + +static void stdout_predictable_latency_event_agg_log( + struct nvme_aggregate_predictable_lat_event *pea_log, + __u64 log_entries, __u32 size, const char *devname) +{ + __u64 num_iter; + __u64 num_entries; + + num_entries = le64_to_cpu(pea_log->num_entries); + printf("Predictable Latency Event Aggregate Log for"\ + " device: %s\n", devname); + + printf("Number of Entries Available: %"PRIu64"\n", + (uint64_t)num_entries); + + num_iter = min(num_entries, log_entries); + for (int i = 0; i < num_iter; i++) { + printf("Entry[%d]: %u\n", i + 1, + le16_to_cpu(pea_log->entries[i])); + } +} + +static void stdout_persistent_event_log_rci(__le32 pel_header_rci) +{ + __u32 rci = le32_to_cpu(pel_header_rci); + __u32 rsvd19 = (rci & 0xfff80000) >> 19; + __u8 rce = (rci & 0x40000) >> 18; + __u8 rcpit = (rci & 0x30000) >> 16; + __u16 rcpid = rci & 0xffff; + + if(rsvd19) + printf(" [31:19] : %#x\tReserved\n", rsvd19); + printf("\tReporting Context Exists (RCE): %s(%u)\n", + rce ? "true" : "false", rce); + printf("\tReporting Context Port Identifier Type (RCPIT): %u(%s)\n", rcpit, + (rcpit == 0x00) ? "Does not already exist" : + (rcpit == 0x01) ? "NVM subsystem port" : + (rcpit == 0x02) ? "NVMe-MI port" : "Reserved"); + printf("\tReporting Context Port Identifier (RCPID): %#x\n\n", rcpid); +} + +static void stdout_persistent_event_entry_ehai(__u8 ehai) +{ + __u8 rsvd1 = (ehai & 0xfc) >> 2; + __u8 pit = ehai & 0x03; + + printf(" [7:2] : %#x\tReserved\n", rsvd1); + printf("\tPort Identifier Type (PIT): %u(%s)\n", pit, + (pit == 0x00) ? "PIT not reported and PELPID does not apply" : + (pit == 0x01) ? "NVM subsystem port" : + (pit == 0x02) ? "NVMe-MI port" : + "Event not associated with any port and PELPID does not apply"); +} + +static void stdout_add_bitmap(int i, __u8 seb) +{ + for (int bit = 0; bit < 8; bit++) { + if (nvme_pel_event_to_string(bit + i * 8)) { + if (nvme_pel_event_to_string(bit + i * 8)) + if ((seb >> bit) & 0x1) + printf(" Support %s\n", + nvme_pel_event_to_string(bit + i * 8)); + } + } +} + +static void stdout_persistent_event_log(void *pevent_log_info, + __u8 action, __u32 size, + const char *devname) +{ + __u32 offset, por_info_len, por_info_list; + __u64 *fw_rev; + int fid, cdw11, dword_cnt; + unsigned char *mem_buf = NULL; + struct nvme_smart_log *smart_event; + struct nvme_fw_commit_event *fw_commit_event; + struct nvme_time_stamp_change_event *ts_change_event; + struct nvme_power_on_reset_info_list *por_event; + struct nvme_nss_hw_err_event *nss_hw_err_event; + struct nvme_change_ns_event *ns_event; + struct nvme_format_nvm_start_event *format_start_event; + struct nvme_format_nvm_compln_event *format_cmpln_event; + struct nvme_sanitize_start_event *sanitize_start_event; + struct nvme_sanitize_compln_event *sanitize_cmpln_event; + struct nvme_set_feature_event *set_feat_event; + struct nvme_thermal_exc_event *thermal_exc_event; + struct nvme_persistent_event_log *pevent_log_head; + struct nvme_persistent_event_entry *pevent_entry_head; + + int human = stdout_print_ops.flags & VERBOSE; + + offset = sizeof(*pevent_log_head); + + printf("Persistent Event Log for device: %s\n", devname); + printf("Action for Persistent Event Log: %u\n", action); + if (size >= offset) { + pevent_log_head = pevent_log_info; + printf("Log Identifier: %u\n", pevent_log_head->lid); + printf("Total Number of Events: %u\n", + le32_to_cpu(pevent_log_head->tnev)); + printf("Total Log Length : %"PRIu64"\n", + le64_to_cpu(pevent_log_head->tll)); + printf("Log Revision: %u\n", pevent_log_head->rv); + printf("Log Header Length: %u\n", pevent_log_head->lhl); + printf("Timestamp: %"PRIu64"\n", + le64_to_cpu(pevent_log_head->ts)); + printf("Power On Hours (POH): %s", + uint128_t_to_l10n_string(le128_to_cpu(pevent_log_head->poh))); + printf("Power Cycle Count: %"PRIu64"\n", + le64_to_cpu(pevent_log_head->pcc)); + printf("PCI Vendor ID (VID): %u\n", + le16_to_cpu(pevent_log_head->vid)); + printf("PCI Subsystem Vendor ID (SSVID): %u\n", + le16_to_cpu(pevent_log_head->ssvid)); + printf("Serial Number (SN): %-.*s\n", + (int)sizeof(pevent_log_head->sn), pevent_log_head->sn); + printf("Model Number (MN): %-.*s\n", + (int)sizeof(pevent_log_head->mn), pevent_log_head->mn); + printf("NVM Subsystem NVMe Qualified Name (SUBNQN): %-.*s\n", + (int)sizeof(pevent_log_head->subnqn), + pevent_log_head->subnqn); + printf("Generation Number: %u\n", + le16_to_cpu(pevent_log_head->gen_number)); + printf("Reporting Context Information (RCI): %u\n", + le32_to_cpu(pevent_log_head->rci)); + if (human) + stdout_persistent_event_log_rci(pevent_log_head->rci); + printf("Supported Events Bitmap: \n"); + for (int i = 0; i < 32; i++) { + if (pevent_log_head->seb[i] == 0) + continue; + stdout_add_bitmap(i, pevent_log_head->seb[i]); + } + } else { + printf("No log data can be shown with this log len at least " \ + "512 bytes is required or can be 0 to read the complete "\ + "log page after context established\n"); + return; + } + printf("\n"); + printf("\nPersistent Event Entries:\n"); + for (int i = 0; i < le32_to_cpu(pevent_log_head->tnev); i++) { + if (offset + sizeof(*pevent_entry_head) >= size) + break; + + pevent_entry_head = pevent_log_info + offset; + + if ((offset + pevent_entry_head->ehl + 3 + + le16_to_cpu(pevent_entry_head->el)) >= size) + break; + printf("Event Number: %u\n", i); + printf("Event Type: %s\n", nvme_pel_event_to_string(pevent_entry_head->etype)); + printf("Event Type Revision: %u\n", pevent_entry_head->etype_rev); + printf("Event Header Length: %u\n", pevent_entry_head->ehl); + printf("Event Header Additional Info: %u\n", pevent_entry_head->ehai); + if (human) + stdout_persistent_event_entry_ehai(pevent_entry_head->ehai); + printf("Controller Identifier: %u\n", + le16_to_cpu(pevent_entry_head->cntlid)); + printf("Event Timestamp: %"PRIu64"\n", + le64_to_cpu(pevent_entry_head->ets)); + printf("Port Identifier: %u\n", + le16_to_cpu(pevent_entry_head->pelpid)); + printf("Vendor Specific Information Length: %u\n", + le16_to_cpu(pevent_entry_head->vsil)); + printf("Event Length: %u\n", le16_to_cpu(pevent_entry_head->el)); + + offset += pevent_entry_head->ehl + 3; + + switch (pevent_entry_head->etype) { + case NVME_PEL_SMART_HEALTH_EVENT: + smart_event = pevent_log_info + offset; + printf("Smart Health Event Entry: \n"); + stdout_smart_log(smart_event, NVME_NSID_ALL, devname); + break; + case NVME_PEL_FW_COMMIT_EVENT: + fw_commit_event = pevent_log_info + offset; + printf("FW Commit Event Entry: \n"); + printf("Old Firmware Revision: %"PRIu64" (%s)\n", + le64_to_cpu(fw_commit_event->old_fw_rev), + util_fw_to_string((char *)&fw_commit_event->old_fw_rev)); + printf("New Firmware Revision: %"PRIu64" (%s)\n", + le64_to_cpu(fw_commit_event->new_fw_rev), + util_fw_to_string((char *)&fw_commit_event->new_fw_rev)); + printf("FW Commit Action: %u\n", + fw_commit_event->fw_commit_action); + printf("FW Slot: %u\n", fw_commit_event->fw_slot); + printf("Status Code Type for Firmware Commit Command: %u\n", + fw_commit_event->sct_fw); + printf("Status Returned for Firmware Commit Command: %u\n", + fw_commit_event->sc_fw); + printf("Vendor Assigned Firmware Commit Result Code: %u\n", + le16_to_cpu(fw_commit_event->vndr_assign_fw_commit_rc)); + break; + case NVME_PEL_TIMESTAMP_EVENT: + ts_change_event = pevent_log_info + offset; + printf("Time Stamp Change Event Entry: \n"); + printf("Previous Timestamp: %"PRIu64"\n", + le64_to_cpu(ts_change_event->previous_timestamp)); + printf("Milliseconds Since Reset: %"PRIu64"\n", + le64_to_cpu(ts_change_event->ml_secs_since_reset)); + break; + case NVME_PEL_POWER_ON_RESET_EVENT: + por_info_len = (le16_to_cpu(pevent_entry_head->el) - + le16_to_cpu(pevent_entry_head->vsil) - sizeof(*fw_rev)); + + por_info_list = por_info_len / sizeof(*por_event); + + printf("Power On Reset Event Entry: \n"); + fw_rev = pevent_log_info + offset; + printf("Firmware Revision: %"PRIu64" (%s)\n", le64_to_cpu(*fw_rev), + util_fw_to_string((char *)fw_rev)); + printf("Reset Information List: \n"); + + for (int i = 0; i < por_info_list; i++) { + por_event = pevent_log_info + offset + + sizeof(*fw_rev) + i * sizeof(*por_event); + printf("Controller ID: %u\n", le16_to_cpu(por_event->cid)); + printf("Firmware Activation: %u\n", + por_event->fw_act); + printf("Operation in Progress: %u\n", + por_event->op_in_prog); + printf("Controller Power Cycle: %u\n", + le32_to_cpu(por_event->ctrl_power_cycle)); + printf("Power on milliseconds: %"PRIu64"\n", + le64_to_cpu(por_event->power_on_ml_seconds)); + printf("Controller Timestamp: %"PRIu64"\n", + le64_to_cpu(por_event->ctrl_time_stamp)); + } + break; + case NVME_PEL_NSS_HW_ERROR_EVENT: + nss_hw_err_event = pevent_log_info + offset; + printf("NVM Subsystem Hardware Error Event Code Entry: %u, %s\n", + le16_to_cpu(nss_hw_err_event->nss_hw_err_event_code), + nvme_nss_hw_error_to_string(nss_hw_err_event->nss_hw_err_event_code)); + break; + case NVME_PEL_CHANGE_NS_EVENT: + ns_event = pevent_log_info + offset; + printf("Change Namespace Event Entry: \n"); + printf("Namespace Management CDW10: %u\n", + le32_to_cpu(ns_event->nsmgt_cdw10)); + printf("Namespace Size: %"PRIu64"\n", + le64_to_cpu(ns_event->nsze)); + printf("Namespace Capacity: %"PRIu64"\n", + le64_to_cpu(ns_event->nscap)); + printf("Formatted LBA Size: %u\n", ns_event->flbas); + printf("End-to-end Data Protection Type Settings: %u\n", + ns_event->dps); + printf("Namespace Multi-path I/O and Namespace Sharing" \ + " Capabilities: %u\n", ns_event->nmic); + printf("ANA Group Identifier: %u\n", + le32_to_cpu(ns_event->ana_grp_id)); + printf("NVM Set Identifier: %u\n", le16_to_cpu(ns_event->nvmset_id)); + printf("Namespace ID: %u\n", le32_to_cpu(ns_event->nsid)); + break; + case NVME_PEL_FORMAT_START_EVENT: + format_start_event = pevent_log_info + offset; + printf("Format NVM Start Event Entry: \n"); + printf("Namespace Identifier: %u\n", + le32_to_cpu(format_start_event->nsid)); + printf("Format NVM Attributes: %u\n", + format_start_event->fna); + printf("Format NVM CDW10: %u\n", + le32_to_cpu(format_start_event->format_nvm_cdw10)); + break; + case NVME_PEL_FORMAT_COMPLETION_EVENT: + format_cmpln_event = pevent_log_info + offset; + printf("Format NVM Completion Event Entry: \n"); + printf("Namespace Identifier: %u\n", + le32_to_cpu(format_cmpln_event->nsid)); + printf("Smallest Format Progress Indicator: %u\n", + format_cmpln_event->smallest_fpi); + printf("Format NVM Status: %u\n", + format_cmpln_event->format_nvm_status); + printf("Completion Information: %u\n", + le16_to_cpu(format_cmpln_event->compln_info)); + printf("Status Field: %u\n", + le32_to_cpu(format_cmpln_event->status_field)); + break; + case NVME_PEL_SANITIZE_START_EVENT: + sanitize_start_event = pevent_log_info + offset; + printf("Sanitize Start Event Entry: \n"); + printf("SANICAP: %u\n", sanitize_start_event->sani_cap); + printf("Sanitize CDW10: %u\n", + le32_to_cpu(sanitize_start_event->sani_cdw10)); + printf("Sanitize CDW11: %u\n", + le32_to_cpu(sanitize_start_event->sani_cdw11)); + break; + case NVME_PEL_SANITIZE_COMPLETION_EVENT: + sanitize_cmpln_event = pevent_log_info + offset; + printf("Sanitize Completion Event Entry: \n"); + printf("Sanitize Progress: %u\n", + le16_to_cpu(sanitize_cmpln_event->sani_prog)); + printf("Sanitize Status: %u\n", + le16_to_cpu(sanitize_cmpln_event->sani_status)); + printf("Completion Information: %u\n", + le16_to_cpu(sanitize_cmpln_event->cmpln_info)); + break; + case NVME_PEL_SET_FEATURE_EVENT: + set_feat_event = pevent_log_info + offset; + printf("Set Feature Event Entry: \n"); + dword_cnt = set_feat_event->layout & 0x03; + fid = le32_to_cpu(set_feat_event->cdw_mem[0]) & 0x000f; + cdw11 = le32_to_cpu(set_feat_event->cdw_mem[1]); + + printf("Set Feature ID :%#02x (%s), value:%#08x\n", fid, + nvme_feature_to_string(fid), cdw11); + if (((set_feat_event->layout & 0xff) >> 2) != 0) { + mem_buf = (unsigned char *)(set_feat_event + 4 + dword_cnt * 4); + stdout_feature_show_fields(fid, cdw11, mem_buf); + } + break; + case NVME_PEL_TELEMETRY_CRT: + d(pevent_log_info + offset, 512, 16, 1); + break; + case NVME_PEL_THERMAL_EXCURSION_EVENT: + thermal_exc_event = pevent_log_info + offset; + printf("Thermal Excursion Event Entry: \n"); + printf("Over Temperature: %u\n", thermal_exc_event->over_temp); + printf("Threshold: %u\n", thermal_exc_event->threshold); + break; + default: + printf("Reserved Event\n\n"); + } + offset += le16_to_cpu(pevent_entry_head->el); + printf("\n"); + } +} + +static void stdout_endurance_group_event_agg_log( + struct nvme_aggregate_predictable_lat_event *endurance_log, + __u64 log_entries, __u32 size, const char *devname) +{ + printf("Endurance Group Event Aggregate Log for"\ + " device: %s\n", devname); + + printf("Number of Entries Available: %"PRIu64"\n", + le64_to_cpu(endurance_log->num_entries)); + + for (int i = 0; i < log_entries; i++) { + printf("Entry[%d]: %u\n", i + 1, + le16_to_cpu(endurance_log->entries[i])); + } +} + +static void stdout_lba_status_log(void *lba_status, __u32 size, + const char *devname) +{ + struct nvme_lba_status_log *hdr; + struct nvme_lbas_ns_element *ns_element; + struct nvme_lba_rd *range_desc; + int offset = sizeof(*hdr); + __u32 num_lba_desc, num_elements; + + hdr = lba_status; + printf("LBA Status Log for device: %s\n", devname); + printf("LBA Status Log Page Length: %"PRIu32"\n", + le32_to_cpu(hdr->lslplen)); + num_elements = le32_to_cpu(hdr->nlslne); + printf("Number of LBA Status Log Namespace Elements: %"PRIu32"\n", + num_elements); + printf("Estimate of Unrecoverable Logical Blocks: %"PRIu32"\n", + le32_to_cpu(hdr->estulb)); + printf("LBA Status Generation Counter: %"PRIu16"\n", le16_to_cpu(hdr->lsgc)); + for (int ele = 0; ele < num_elements; ele++) { + ns_element = lba_status + offset; + printf("Namespace Element Identifier: %"PRIu32"\n", + le32_to_cpu(ns_element->neid)); + num_lba_desc = le32_to_cpu(ns_element->nlrd); + printf("Number of LBA Range Descriptors: %"PRIu32"\n", num_lba_desc); + printf("Recommended Action Type: %u\n", ns_element->ratype); + + offset += sizeof(*ns_element); + if (num_lba_desc != 0xffffffff) { + for (int i = 0; i < num_lba_desc; i++) { + range_desc = lba_status + offset; + printf("RSLBA[%d]: %"PRIu64"\n", i, + le64_to_cpu(range_desc->rslba)); + printf("RNLB[%d]: %"PRIu32"\n", i, + le32_to_cpu(range_desc->rnlb)); + offset += sizeof(*range_desc); + } + } else { + printf("Number of LBA Range Descriptors (NLRD) set to %#x for "\ + "NS element %d\n", num_lba_desc, ele); + } + } +} + +static void stdout_resv_notif_log(struct nvme_resv_notification_log *resv, + const char *devname) +{ + printf("Reservation Notif Log for device: %s\n", devname); + printf("Log Page Count : %"PRIx64"\n", + le64_to_cpu(resv->lpc)); + printf("Resv Notif Log Page Type : %u (%s)\n", + resv->rnlpt, + nvme_resv_notif_to_string(resv->rnlpt)); + printf("Num of Available Log Pages : %u\n", resv->nalp); + printf("Namespace ID: : %"PRIx32"\n", + le32_to_cpu(resv->nsid)); +} + +static void stdout_fid_support_effects_log_human(__u32 fid_support) +{ + const char *set = "+"; + const char *clr = "-"; + __u16 fsp; + + printf(" FSUPP+"); + printf(" UDCC%s", (fid_support & NVME_FID_SUPPORTED_EFFECTS_UDCC) ? set : clr); + printf(" NCC%s", (fid_support & NVME_FID_SUPPORTED_EFFECTS_NCC) ? set : clr); + printf(" NIC%s", (fid_support & NVME_FID_SUPPORTED_EFFECTS_NIC) ? set : clr); + printf(" CCC%s", (fid_support & NVME_FID_SUPPORTED_EFFECTS_CCC) ? set : clr); + printf(" USS%s", (fid_support & NVME_FID_SUPPORTED_EFFECTS_UUID_SEL) ? set : clr); + + fsp = (fid_support >> NVME_FID_SUPPORTED_EFFECTS_SCOPE_SHIFT) & NVME_FID_SUPPORTED_EFFECTS_SCOPE_MASK; + + printf(" NAMESPACE SCOPE%s", (fsp & NVME_FID_SUPPORTED_EFFECTS_SCOPE_NS) ? set : clr); + printf(" CONTROLLER SCOPE%s", (fsp & NVME_FID_SUPPORTED_EFFECTS_SCOPE_CTRL) ? set : clr); + printf(" NVM SET SCOPE%s", (fsp & NVME_FID_SUPPORTED_EFFECTS_SCOPE_NVM_SET) ? set : clr); + printf(" ENDURANCE GROUP SCOPE%s", (fsp & NVME_FID_SUPPORTED_EFFECTS_SCOPE_ENDGRP) ? set : clr); + printf(" DOMAIN SCOPE%s", (fsp & NVME_FID_SUPPORTED_EFFECTS_SCOPE_DOMAIN) ? set : clr); + printf(" NVM Subsystem SCOPE%s", (fsp & NVME_FID_SUPPORTED_EFFECTS_SCOPE_NSS) ? set : clr); +} + +static void stdout_fid_support_effects_log(struct nvme_fid_supported_effects_log *fid_log, + const char *devname) +{ + __u32 fid_effect; + int i, human = stdout_print_ops.flags & VERBOSE; + + printf("FID Supports Effects Log for device: %s\n", devname); + printf("Admin Command Set\n"); + for (i = 0; i < 256; i++) { + fid_effect = le32_to_cpu(fid_log->fid_support[i]); + if (fid_effect & NVME_FID_SUPPORTED_EFFECTS_FSUPP) { + printf("FID %02x -> Support Effects Log: %08x", i, + fid_effect); + if (human) + stdout_fid_support_effects_log_human(fid_effect); + else + printf("\n"); + } + } +} + +static void stdout_mi_cmd_support_effects_log_human(__u32 mi_cmd_support) +{ + const char *set = "+"; + const char *clr = "-"; + __u16 csp; + + printf(" CSUPP+"); + printf(" UDCC%s", (mi_cmd_support & NVME_MI_CMD_SUPPORTED_EFFECTS_UDCC) ? set : clr); + printf(" NCC%s", (mi_cmd_support & NVME_MI_CMD_SUPPORTED_EFFECTS_NCC) ? set : clr); + printf(" NIC%s", (mi_cmd_support & NVME_MI_CMD_SUPPORTED_EFFECTS_NIC) ? set : clr); + printf(" CCC%s", (mi_cmd_support & NVME_MI_CMD_SUPPORTED_EFFECTS_CCC) ? set : clr); + + csp = (mi_cmd_support >> NVME_MI_CMD_SUPPORTED_EFFECTS_SCOPE_SHIFT) & NVME_MI_CMD_SUPPORTED_EFFECTS_SCOPE_MASK; + + printf(" NAMESPACE SCOPE%s", (csp & NVME_MI_CMD_SUPPORTED_EFFECTS_SCOPE_NS) ? set : clr); + printf(" CONTROLLER SCOPE%s", (csp & NVME_MI_CMD_SUPPORTED_EFFECTS_SCOPE_CTRL) ? set : clr); + printf(" NVM SET SCOPE%s", (csp & NVME_MI_CMD_SUPPORTED_EFFECTS_SCOPE_NVM_SET) ? set : clr); + printf(" ENDURANCE GROUP SCOPE%s", (csp & NVME_MI_CMD_SUPPORTED_EFFECTS_SCOPE_ENDGRP) ? set : clr); + printf(" DOMAIN SCOPE%s", (csp & NVME_MI_CMD_SUPPORTED_EFFECTS_SCOPE_DOMAIN) ? set : clr); + printf(" NVM Subsystem SCOPE%s", (csp & NVME_MI_CMD_SUPPORTED_EFFECTS_SCOPE_NSS) ? set : clr); +} + +static void stdout_mi_cmd_support_effects_log(struct nvme_mi_cmd_supported_effects_log *mi_cmd_log, + const char *devname) +{ + __u32 mi_cmd_effect; + int i, human = stdout_print_ops.flags & VERBOSE; + + printf("MI Commands Support Effects Log for device: %s\n", devname); + printf("Admin Command Set\n"); + for (i = 0; i < NVME_LOG_MI_CMD_SUPPORTED_EFFECTS_MAX; i++) { + mi_cmd_effect = le32_to_cpu(mi_cmd_log->mi_cmd_support[i]); + if (mi_cmd_effect & NVME_MI_CMD_SUPPORTED_EFFECTS_CSUPP) { + printf("MI CMD %02x -> Support Effects Log: %08x", i, + mi_cmd_effect); + if (human) + stdout_mi_cmd_support_effects_log_human(mi_cmd_effect); + else + printf("\n"); + } + } +} + +static void stdout_boot_part_log(void *bp_log, const char *devname, + __u32 size) +{ + struct nvme_boot_partition *hdr; + + hdr = bp_log; + printf("Boot Partition Log for device: %s\n", devname); + printf("Log ID: %u\n", hdr->lid); + printf("Boot Partition Size: %u KiB\n", le32_to_cpu(hdr->bpinfo) & 0x7fff); + printf("Active BPID: %u\n", (le32_to_cpu(hdr->bpinfo) >> 31) & 0x1); +} + +static void stdout_media_unit_stat_log(struct nvme_media_unit_stat_log *mus_log) +{ + int i; + int nmu = le16_to_cpu(mus_log->nmu); + + printf("Number of Media Unit Status Descriptors: %u\n", nmu); + printf("Number of Channels: %u\n", le16_to_cpu(mus_log->cchans)); + printf("Selected Configuration: %u\n", le16_to_cpu(mus_log->sel_config)); + for (i = 0; i < nmu; i++) { + printf("Media Unit Status Descriptor: %u\n", i); + printf("Media Unit Identifier: %u\n", + le16_to_cpu(mus_log->mus_desc[i].muid)); + printf("Domain Identifier: %u\n", + le16_to_cpu(mus_log->mus_desc[i].domainid)); + printf("Endurance Group Identifier: %u\n", + le16_to_cpu(mus_log->mus_desc[i].endgid)); + printf("NVM Set Identifier: %u\n", + le16_to_cpu(mus_log->mus_desc[i].nvmsetid)); + printf("Capacity Adjustment Factor: %u\n", + le16_to_cpu(mus_log->mus_desc[i].cap_adj_fctr)); + printf("Available Spare: %u\n", mus_log->mus_desc[i].avl_spare); + printf("Percentage Used: %u\n", mus_log->mus_desc[i].percent_used); + printf("Number of Channels: %u\n", mus_log->mus_desc[i].mucs); + printf("Channel Identifiers Offset: %u\n", mus_log->mus_desc[i].cio); + } +} + +static void stdout_fdp_config_fdpa(uint8_t fdpa) +{ + __u8 valid = (fdpa >> 7) & 0x1; + __u8 rsvd = (fdpa >> 5) >> 0x3; + __u8 fdpvwc = (fdpa >> 4) & 0x1; + __u8 rgif = fdpa & 0xf; + + printf(" [7:7] : %#x\tFDP Configuration %sValid\n", + valid, valid ? "" : "Not "); + if (rsvd) + printf(" [6:5] : %#x\tReserved\n", rsvd); + printf(" [4:4] : %#x\tFDP Volatile Write Cache %sPresent\n", + fdpvwc, fdpvwc ? "" : "Not "); + printf(" [3:0] : %#x\tReclaim Group Identifier Format\n", rgif); +} + +static void stdout_fdp_configs(struct nvme_fdp_config_log *log, size_t len) +{ + void *p = log->configs; + int human = stdout_print_ops.flags & VERBOSE; + uint16_t n; + + n = le16_to_cpu(log->n) + 1; + + for (int i = 0; i < n; i++) { + struct nvme_fdp_config_desc *config = p; + + printf("FDP Attributes: %#x\n", config->fdpa); + if (human) + stdout_fdp_config_fdpa(config->fdpa); + + printf("Vendor Specific Size: %u\n", config->vss); + printf("Number of Reclaim Groups: %"PRIu32"\n", le32_to_cpu(config->nrg)); + printf("Number of Reclaim Unit Handles: %"PRIu16"\n", le16_to_cpu(config->nruh)); + printf("Number of Namespaces Supported: %"PRIu32"\n", le32_to_cpu(config->nnss)); + printf("Reclaim Unit Nominal Size: %"PRIu64"\n", le64_to_cpu(config->runs)); + printf("Estimated Reclaim Unit Time Limit: %"PRIu32"\n", le32_to_cpu(config->erutl)); + + printf("Reclaim Unit Handle List:\n"); + for (int j = 0; j < le16_to_cpu(config->nruh); j++) { + struct nvme_fdp_ruh_desc *ruh = &config->ruhs[j]; + + printf(" [%d]: %s\n", j, ruh->ruht == NVME_FDP_RUHT_INITIALLY_ISOLATED ? "Initially Isolated" : "Persistently Isolated"); + } + + p += config->size; + } +} + +static void stdout_fdp_usage(struct nvme_fdp_ruhu_log *log, size_t len) +{ + uint16_t nruh = le16_to_cpu(log->nruh); + + for (int i = 0; i < nruh; i++) { + struct nvme_fdp_ruhu_desc *ruhu = &log->ruhus[i]; + + printf("Reclaim Unit Handle %d Attributes: 0x%"PRIx8" (%s)\n", i, ruhu->ruha, + ruhu->ruha == 0x0 ? "Unused" : ( + ruhu->ruha == 0x1 ? "Host Specified" : ( + ruhu->ruha == 0x2 ? "Controller Specified" : "Unknown"))); + } +} + +static void stdout_fdp_stats(struct nvme_fdp_stats_log *log) +{ + printf("Host Bytes with Metadata Written (HBMW): %s\n", + uint128_t_to_l10n_string(le128_to_cpu(log->hbmw))); + printf("Media Bytes with Metadata Written (MBMW): %s\n", + uint128_t_to_l10n_string(le128_to_cpu(log->mbmw))); + printf("Media Bytes Erased (MBE): %s\n", + uint128_t_to_l10n_string(le128_to_cpu(log->mbe))); +} + +static void stdout_fdp_events(struct nvme_fdp_events_log *log) +{ + struct tm *tm; + char buffer[320]; + time_t ts; + uint32_t n = le32_to_cpu(log->n); + + for (unsigned int i = 0; i < n; i++) { + struct nvme_fdp_event *event = &log->events[i]; + + ts = int48_to_long(event->ts.timestamp) / 1000; + tm = localtime(&ts); + + printf("Event[%u]\n", i); + printf(" Event Type: 0x%"PRIx8" (%s)\n", event->type, nvme_fdp_event_to_string(event->type)); + printf(" Event Timestamp: %"PRIu64" (%s)\n", int48_to_long(event->ts.timestamp), + strftime(buffer, sizeof(buffer), "%c %Z", tm) ? buffer : "-"); + + if (event->flags & NVME_FDP_EVENT_F_PIV) + printf(" Placement Identifier (PID): 0x%"PRIx16"\n", le16_to_cpu(event->pid)); + + if (event->flags & NVME_FDP_EVENT_F_NSIDV) + printf(" Namespace Identifier (NSID): %"PRIu32"\n", le32_to_cpu(event->nsid)); + + if (event->type == NVME_FDP_EVENT_REALLOC) { + struct nvme_fdp_event_realloc *mr; + mr = (struct nvme_fdp_event_realloc *)&event->type_specific; + + printf(" Number of LBAs Moved (NLBAM): %"PRIu16"\n", le16_to_cpu(mr->nlbam)); + + if (mr->flags & NVME_FDP_EVENT_REALLOC_F_LBAV) { + printf(" Logical Block Address (LBA): 0x%"PRIx64"\n", le64_to_cpu(mr->lba)); + } + } + + if (event->flags & NVME_FDP_EVENT_F_LV) { + printf(" Reclaim Group Identifier: %"PRIu16"\n", le16_to_cpu(event->rgid)); + printf(" Reclaim Unit Handle Identifier %"PRIu8"\n", event->ruhid); + } + + printf("\n"); + } +} + +static void stdout_fdp_ruh_status(struct nvme_fdp_ruh_status *status, size_t len) +{ + uint16_t nruhsd = le16_to_cpu(status->nruhsd); + + for (unsigned int i = 0; i < nruhsd; i++) { + struct nvme_fdp_ruh_status_desc *ruhs = &status->ruhss[i]; + + printf("Placement Identifier %"PRIu16"; Reclaim Unit Handle Identifier %"PRIu16"\n", + le16_to_cpu(ruhs->pid), le16_to_cpu(ruhs->ruhid)); + printf(" Estimated Active Reclaim Unit Time Remaining (EARUTR): %"PRIu32"\n", + le32_to_cpu(ruhs->earutr)); + printf(" Reclaim Unit Available Media Writes (RUAMW): %"PRIu64"\n", + le64_to_cpu(ruhs->ruamw)); + + printf("\n"); + } +} + +static void stdout_supported_cap_config_log(struct nvme_supported_cap_config_list_log *cap) +{ + struct nvme_end_grp_chan_desc *chan_desc; + int i, j, k, l, m, sccn, egcn, egsets, egchans, chmus; + + sccn = cap->sccn; + printf("Number of Supported Capacity Configurations: %u\n", sccn); + for (i = 0; i < sccn; i++) { + printf("Capacity Configuration Descriptor: %u\n", i); + printf("Capacity Configuration Identifier: %u\n", + le16_to_cpu(cap->cap_config_desc[i].cap_config_id)); + printf("Domain Identifier: %u\n", + le16_to_cpu(cap->cap_config_desc[i].domainid)); + egcn = le16_to_cpu(cap->cap_config_desc[i].egcn); + printf("Number of Endurance Group Configuration Descriptors: %u\n", egcn); + for(j = 0; j < egcn; j++) { + printf("Endurance Group Identifier: %u\n", + le16_to_cpu(cap->cap_config_desc[i].egcd[j].endgid)); + printf("Capacity Adjustment Factor: %u\n", + le16_to_cpu(cap->cap_config_desc[i].egcd[j].cap_adj_factor)); + printf("Total Endurance Group Capacity: %s\n", + uint128_t_to_l10n_string(le128_to_cpu( + cap->cap_config_desc[i].egcd[j].tegcap))); + printf("Spare Endurance Group Capacity: %s\n", + uint128_t_to_l10n_string(le128_to_cpu( + cap->cap_config_desc[i].egcd[j].segcap))); + printf("Endurance Estimate: %s\n", + uint128_t_to_l10n_string(le128_to_cpu( + cap->cap_config_desc[i].egcd[j].end_est))); + egsets = le16_to_cpu(cap->cap_config_desc[i].egcd[j].egsets); + printf("Number of NVM Sets: %u\n", egsets); + for(k = 0; k < egsets; k++) { + printf("NVM Set %d Identifier: %u\n", i, + le16_to_cpu(cap->cap_config_desc[i].egcd[j].nvmsetid[k])); + } + chan_desc = (struct nvme_end_grp_chan_desc *) \ + ((cap->cap_config_desc[i].egcd[j].nvmsetid[0]) * (sizeof(__u16)*egsets)); + egchans = le16_to_cpu(chan_desc->egchans); + printf("Number of Channels: %u\n", egchans); + for(l = 0; l < egchans; l++) { + printf("Channel Identifier: %u\n", + le16_to_cpu(chan_desc->chan_config_desc[l].chanid)); + chmus = le16_to_cpu(chan_desc->chan_config_desc[l].chmus); + printf("Number of Channel Media Units: %u\n", chmus); + for(m = 0; m < chmus; m++) { + printf("Media Unit Identifier: %u\n", + le16_to_cpu(chan_desc->chan_config_desc[l].mu_config_desc[m].muid)); + printf("Media Unit Descriptor Length: %u\n", + le16_to_cpu(chan_desc->chan_config_desc[l].mu_config_desc[m].mudl)); + } + } + } + } +} + +static unsigned int stdout_subsystem_multipath(nvme_subsystem_t s, + bool show_ana) +{ + nvme_ns_t n; + nvme_path_t p; + unsigned int i = 0; + + n = nvme_subsystem_first_ns(s); + if (!n) + return 0; + + nvme_namespace_for_each_path(n, p) { + nvme_ctrl_t c = nvme_path_get_ctrl(p); + const char *ana_state = ""; + + if (show_ana) + ana_state = nvme_path_get_ana_state(p); + + printf(" +- %s %s %s %s %s\n", + nvme_ctrl_get_name(c), + nvme_ctrl_get_transport(c), + nvme_ctrl_get_address(c), + nvme_ctrl_get_state(c), + ana_state); + i++; + } + + return i; +} + +static void stdout_subsystem_ctrls(nvme_subsystem_t s) +{ + nvme_ctrl_t c; + + nvme_subsystem_for_each_ctrl(s, c) { + printf(" +- %s %s %s %s\n", + nvme_ctrl_get_name(c), + nvme_ctrl_get_transport(c), + nvme_ctrl_get_address(c), + nvme_ctrl_get_state(c)); + } +} + +static void stdout_subsystem(nvme_root_t r, bool show_ana) +{ + nvme_host_t h; + + nvme_for_each_host(r, h) { + nvme_subsystem_t s; + + nvme_for_each_subsystem(h, s) { + printf("%s - NQN=%s\n", nvme_subsystem_get_name(s), + nvme_subsystem_get_nqn(s)); + printf("\\\n"); + + if (!stdout_subsystem_multipath(s, show_ana)) + stdout_subsystem_ctrls(s); + } + } +} + +static void stdout_subsystem_list(nvme_root_t r, bool show_ana) +{ + stdout_subsystem(r, show_ana); +} + +static void stdout_registers_cap(struct nvme_bar_cap *cap) +{ + printf("\tController Ready With Media Support (CRWMS): %s\n", + ((cap->rsvd_crms_nsss_cmbs_pmrs & 0x08) >> 3) ? "Supported" : "Not Supported"); + printf("\tController Ready Independent of Media Support (CRIMS): %s\n", + ((cap->rsvd_crms_nsss_cmbs_pmrs & 0x10) >> 4) ? "Supported" : "Not Supported"); + printf("\tController Memory Buffer Supported (CMBS): The Controller Memory Buffer is %s\n", + ((cap->rsvd_crms_nsss_cmbs_pmrs & 0x02) >> 1) ? "Supported" : + "Not Supported"); + printf("\tPersistent Memory Region Supported (PMRS): The Persistent Memory Region is %s\n", + (cap->rsvd_crms_nsss_cmbs_pmrs & 0x01) ? "Supported" : "Not Supported"); + printf("\tMemory Page Size Maximum (MPSMAX): %u bytes\n", + 1 << (12 + ((cap->mpsmax_mpsmin & 0xf0) >> 4))); + printf("\tMemory Page Size Minimum (MPSMIN): %u bytes\n", + 1 << (12 + (cap->mpsmax_mpsmin & 0x0f))); + printf("\tBoot Partition Support (BPS): %s\n", + (cap->bps_css_nssrs_dstrd & 0x2000) ? "Yes":"No"); + printf("\tCommand Sets Supported (CSS): NVM command set is %s\n", + (cap->bps_css_nssrs_dstrd & 0x0020) ? "Supported" : "Not Supported"); + printf("\t One or more I/O Command Sets are %s\n", + (cap->bps_css_nssrs_dstrd & 0x0800) ? "Supported" : "Not Supported"); + printf("\t %s\n", + (cap->bps_css_nssrs_dstrd & 0x1000) ? "Only Admin Command Set Supported" : + "I/O Command Set is Supported"); + printf("\tNVM Subsystem Reset Supported (NSSRS): %s\n", + (cap->bps_css_nssrs_dstrd & 0x0010) ? "Yes":"No"); + printf("\tDoorbell Stride (DSTRD): %u bytes\n", + 1 << (2 + (cap->bps_css_nssrs_dstrd & 0x000f))); + printf("\tTimeout (TO): %u ms\n", + cap->to * 500); + printf("\tArbitration Mechanism Supported (AMS): Weighted Round Robin with Urgent Priority Class is %s\n", + (cap->ams_cqr & 0x02) ? "supported":"not supported"); + printf("\tContiguous Queues Required (CQR): %s\n", + (cap->ams_cqr & 0x01) ? "Yes":"No"); + printf("\tMaximum Queue Entries Supported (MQES): %u\n\n", + cap->mqes + 1); +} + +static void stdout_registers_version(__u32 vs) +{ + printf("\tNVMe specification %d.%d\n\n", (vs & 0xffff0000) >> 16, + (vs & 0x0000ff00) >> 8); +} + +static void stdout_registers_cc_ams (__u8 ams) +{ + printf("\tArbitration Mechanism Selected (AMS): "); + switch (ams) { + case 0: + printf("Round Robin\n"); + break; + case 1: + printf("Weighted Round Robin with Urgent Priority Class\n"); + break; + case 7: + printf("Vendor Specific\n"); + break; + default: + printf("Reserved\n"); + } +} + +static void stdout_registers_cc_shn (__u8 shn) +{ + printf("\tShutdown Notification (SHN): "); + switch (shn) { + case 0: + printf("No notification; no effect\n"); + break; + case 1: + printf("Normal shutdown notification\n"); + break; + case 2: + printf("Abrupt shutdown notification\n"); + break; + default: + printf("Reserved\n"); + } +} + +static void stdout_registers_cc(__u32 cc) +{ + printf("\tController Ready Independent of Media Enable (CRIME): %s\n", + NVME_CC_CRIME(cc) ? "Enabled":"Disabled"); + + printf("\tI/O Completion Queue Entry Size (IOCQES): %u bytes\n", + 1 << ((cc & 0x00f00000) >> NVME_CC_IOCQES_SHIFT)); + printf("\tI/O Submission Queue Entry Size (IOSQES): %u bytes\n", + 1 << ((cc & 0x000f0000) >> NVME_CC_IOSQES_SHIFT)); + stdout_registers_cc_shn((cc & 0x0000c000) >> NVME_CC_SHN_SHIFT); + stdout_registers_cc_ams((cc & 0x00003800) >> NVME_CC_AMS_SHIFT); + printf("\tMemory Page Size (MPS): %u bytes\n", + 1 << (12 + ((cc & 0x00000780) >> NVME_CC_MPS_SHIFT))); + printf("\tI/O Command Set Selected (CSS): %s\n", + (cc & 0x00000070) == 0x00 ? "NVM Command Set" : + (cc & 0x00000070) == 0x60 ? "All supported I/O Command Sets" : + (cc & 0x00000070) == 0x70 ? "Admin Command Set only" : "Reserved"); + printf("\tEnable (EN): %s\n\n", + (cc & 0x00000001) ? "Yes":"No"); +} + +static void stdout_registers_csts_shst(__u8 shst) +{ + printf("\tShutdown Status (SHST): "); + switch (shst) { + case 0: + printf("Normal operation (no shutdown has been requested)\n"); + break; + case 1: + printf("Shutdown processing occurring\n"); + break; + case 2: + printf("Shutdown processing complete\n"); + break; + default: + printf("Reserved\n"); + } +} + +static void stdout_registers_csts(__u32 csts) +{ + printf("\tProcessing Paused (PP): %s\n", + (csts & 0x00000020) ? "Yes":"No"); + printf("\tNVM Subsystem Reset Occurred (NSSRO): %s\n", + (csts & 0x00000010) ? "Yes":"No"); + stdout_registers_csts_shst((csts & 0x0000000c) >> 2); + printf("\tController Fatal Status (CFS): %s\n", + (csts & 0x00000002) ? "True":"False"); + printf("\tReady (RDY): %s\n\n", + (csts & 0x00000001) ? "Yes":"No"); + +} + +static void stdout_registers_crto(__u32 crto) +{ + printf("\tCRIMT : %d secs\n", + NVME_CRTO_CRIMT(crto)/2 ); + printf("\tCRWMT : %d secs\n", + NVME_CRTO_CRWMT(crto)/2 ); +} + +static void stdout_registers_aqa(__u32 aqa) +{ + printf("\tAdmin Completion Queue Size (ACQS): %u\n", + ((aqa & 0x0fff0000) >> 16) + 1); + printf("\tAdmin Submission Queue Size (ASQS): %u\n\n", + (aqa & 0x00000fff) + 1); + +} + +static void stdout_registers_cmbloc(__u32 cmbloc, __u32 cmbsz) +{ + static const char *enforced[] = { "Enforced", "Not Enforced" }; + + if (cmbsz == 0) { + printf("\tController Memory Buffer feature is not supported\n\n"); + return; + } + printf("\tOffset (OFST): 0x%x (See cmbsz.szu for granularity)\n", + (cmbloc & 0xfffff000) >> 12); + + printf("\tCMB Queue Dword Alignment (CQDA): %d\n", + (cmbloc & 0x00000100) >> 8); + + printf("\tCMB Data Metadata Mixed Memory Support (CDMMMS): %s\n", + enforced[(cmbloc & 0x00000080) >> 7]); + + printf("\tCMB Data Pointer and Command Independent Locations Support (CDPCILS): %s\n", + enforced[(cmbloc & 0x00000040) >> 6]); + + printf("\tCMB Data Pointer Mixed Locations Support (CDPMLS): %s\n", + enforced[(cmbloc & 0x00000020) >> 5]); + + printf("\tCMB Queue Physically Discontiguous Support (CQPDS): %s\n", + enforced[(cmbloc & 0x00000010) >> 4]); + + printf("\tCMB Queue Mixed Memory Support (CQMMS): %s\n", + enforced[(cmbloc & 0x00000008) >> 3]); + + printf("\tBase Indicator Register (BIR): 0x%x\n\n", + (cmbloc & 0x00000007)); +} + +static void stdout_registers_cmbsz(__u32 cmbsz) +{ + if (cmbsz == 0) { + printf("\tController Memory Buffer feature is not supported\n\n"); + return; + } + printf("\tSize (SZ): %u\n", + (cmbsz & 0xfffff000) >> 12); + printf("\tSize Units (SZU): %s\n", + nvme_register_szu_to_string((cmbsz & 0x00000f00) >> 8)); + printf("\tWrite Data Support (WDS): Write Data and metadata transfer in Controller Memory Buffer is %s\n", + (cmbsz & 0x00000010) ? "Supported":"Not supported"); + printf("\tRead Data Support (RDS): Read Data and metadata transfer in Controller Memory Buffer is %s\n", + (cmbsz & 0x00000008) ? "Supported":"Not supported"); + printf("\tPRP SGL List Support (LISTS): PRP/SG Lists in Controller Memory Buffer is %s\n", + (cmbsz & 0x00000004) ? "Supported":"Not supported"); + printf("\tCompletion Queue Support (CQS): Admin and I/O Completion Queues in Controller Memory Buffer is %s\n", + (cmbsz & 0x00000002) ? "Supported":"Not supported"); + printf("\tSubmission Queue Support (SQS): Admin and I/O Submission Queues in Controller Memory Buffer is %s\n\n", + (cmbsz & 0x00000001) ? "Supported":"Not supported"); +} + +static void stdout_registers_bpinfo_brs(__u8 brs) +{ + printf("\tBoot Read Status (BRS): "); + switch (brs) { + case 0: + printf("No Boot Partition read operation requested\n"); + break; + case 1: + printf("Boot Partition read in progress\n"); + break; + case 2: + printf("Boot Partition read completed successfully\n"); + break; + case 3: + printf("Error completing Boot Partition read\n"); + break; + default: + printf("Invalid\n"); + } +} + +static void stdout_registers_bpinfo(__u32 bpinfo) +{ + printf("\tActive Boot Partition ID (ABPID): %u\n", + (bpinfo & 0x80000000) >> 31); + stdout_registers_bpinfo_brs((bpinfo & 0x03000000) >> 24); + printf("\tBoot Partition Size (BPSZ): %u\n", + bpinfo & 0x00007fff); +} + +static void stdout_registers_bprsel(__u32 bprsel) +{ + printf("\tBoot Partition Identifier (BPID): %u\n", + (bprsel & 0x80000000) >> 31); + printf("\tBoot Partition Read Offset (BPROF): %x\n", + (bprsel & 0x3ffffc00) >> 10); + printf("\tBoot Partition Read Size (BPRSZ): %x\n", + bprsel & 0x000003ff); +} + +static void stdout_registers_bpmbl(uint64_t bpmbl) +{ + + printf("\tBoot Partition Memory Buffer Base Address (BMBBA): %"PRIx64"\n", + bpmbl); +} + +static void stdout_registers_cmbmsc(uint64_t cmbmsc) +{ + printf("\tController Base Address (CBA): %" PRIx64 "\n", + (cmbmsc & 0xfffffffffffff000) >> 12); + printf("\tController Memory Space Enable (CMSE): %" PRIx64 "\n", + (cmbmsc & 0x0000000000000002) >> 1); + printf("\tCapabilities Registers Enabled (CRE): CMBLOC and "\ + "CMBSZ registers are%senabled\n\n", + (cmbmsc & 0x0000000000000001) ? " " : " NOT "); +} + +static void stdout_registers_cmbsts(__u32 cmbsts) +{ + printf("\tController Base Address Invalid (CBAI): %x\n\n", + (cmbsts & 0x00000001)); +} + +static void stdout_registers_pmrcap(__u32 pmrcap) +{ + printf("\tController Memory Space Supported (CMSS): "\ + "Referencing PMR with host supplied addresses is %s\n", + ((pmrcap & 0x01000000) >> 24) ? "Supported" : "Not Supported"); + printf("\tPersistent Memory Region Timeout (PMRTO): %x\n", + (pmrcap & 0x00ff0000) >> 16); + printf("\tPersistent Memory Region Write Barrier Mechanisms (PMRWBM): %x\n", + (pmrcap & 0x00003c00) >> 10); + printf("\tPersistent Memory Region Time Units (PMRTU): PMR time unit is %s\n", + (pmrcap & 0x00000300) >> 8 ? "minutes":"500 milliseconds"); + printf("\tBase Indicator Register (BIR): %x\n", + (pmrcap & 0x000000e0) >> 5); + printf("\tWrite Data Support (WDS): Write data to the PMR is %s\n", + (pmrcap & 0x00000010) ? "supported":"not supported"); + printf("\tRead Data Support (RDS): Read data from the PMR is %s\n", + (pmrcap & 0x00000008) ? "supported":"not supported"); +} + +static void stdout_registers_pmrctl(__u32 pmrctl) +{ + printf("\tEnable (EN): PMR is %s\n", (pmrctl & 0x00000001) ? + "READY" : "Disabled"); +} + +static void stdout_registers_pmrsts(__u32 pmrsts, __u32 pmrctl) +{ + printf("\tController Base Address Invalid (CBAI): %x\n", + (pmrsts & 0x00001000) >> 12); + printf("\tHealth Status (HSTS): %s\n", + nvme_register_pmr_hsts_to_string((pmrsts & 0x00000e00) >> 9)); + printf("\tNot Ready (NRDY): "\ + "The Persistent Memory Region is %s to process "\ + "PCI Express memory read and write requests\n", + (pmrsts & 0x00000100) == 0 && (pmrctl & 0x00000001) ? + "READY":"Not Ready"); + printf("\tError (ERR): %x\n", (pmrsts & 0x000000ff)); +} + +static void stdout_registers_pmrebs(__u32 pmrebs) +{ + printf("\tPMR Elasticity Buffer Size Base (PMRWBZ): %x\n", (pmrebs & 0xffffff00) >> 8); + printf("\tRead Bypass Behavior : memory reads not conflicting with memory writes "\ + "in the PMR Elasticity Buffer %s bypass those memory writes\n", + (pmrebs & 0x00000010) ? "SHALL":"MAY"); + printf("\tPMR Elasticity Buffer Size Units (PMRSZU): %s\n", + nvme_register_pmr_pmrszu_to_string(pmrebs & 0x0000000f)); +} + +static void stdout_registers_pmrswtp(__u32 pmrswtp) +{ + printf("\tPMR Sustained Write Throughput (PMRSWTV): %x\n", + (pmrswtp & 0xffffff00) >> 8); + printf("\tPMR Sustained Write Throughput Units (PMRSWTU): %s/second\n", + nvme_register_pmr_pmrszu_to_string(pmrswtp & 0x0000000f)); +} + +static void stdout_registers_pmrmscl(uint32_t pmrmscl) +{ + printf("\tController Base Address (CBA): %#x\n", + (pmrmscl & 0xfffff000) >> 12); + printf("\tController Memory Space Enable (CMSE): %#x\n\n", + (pmrmscl & 0x00000002) >> 1); +} + +static void stdout_registers_pmrmscu(uint32_t pmrmscu) +{ + printf("\tController Base Address (CBA): %#x\n", + pmrmscu); +} + +void stdout_ctrl_registers(void *bar, bool fabrics) +{ + uint64_t cap, asq, acq, bpmbl, cmbmsc; + uint32_t vs, intms, intmc, cc, csts, nssr, crto, aqa, cmbsz, cmbloc, bpinfo, + bprsel, cmbsts, pmrcap, pmrctl, pmrsts, pmrebs, pmrswtp, + pmrmscl, pmrmscu; + int human = stdout_print_ops.flags & VERBOSE; + + cap = mmio_read64(bar + NVME_REG_CAP); + vs = mmio_read32(bar + NVME_REG_VS); + intms = mmio_read32(bar + NVME_REG_INTMS); + intmc = mmio_read32(bar + NVME_REG_INTMC); + cc = mmio_read32(bar + NVME_REG_CC); + csts = mmio_read32(bar + NVME_REG_CSTS); + nssr = mmio_read32(bar + NVME_REG_NSSR); + crto = mmio_read32(bar + NVME_REG_CRTO); + aqa = mmio_read32(bar + NVME_REG_AQA); + asq = mmio_read64(bar + NVME_REG_ASQ); + acq = mmio_read64(bar + NVME_REG_ACQ); + cmbloc = mmio_read32(bar + NVME_REG_CMBLOC); + cmbsz = mmio_read32(bar + NVME_REG_CMBSZ); + bpinfo = mmio_read32(bar + NVME_REG_BPINFO); + bprsel = mmio_read32(bar + NVME_REG_BPRSEL); + bpmbl = mmio_read64(bar + NVME_REG_BPMBL); + cmbmsc = mmio_read64(bar + NVME_REG_CMBMSC); + cmbsts = mmio_read32(bar + NVME_REG_CMBSTS); + pmrcap = mmio_read32(bar + NVME_REG_PMRCAP); + pmrctl = mmio_read32(bar + NVME_REG_PMRCTL); + pmrsts = mmio_read32(bar + NVME_REG_PMRSTS); + pmrebs = mmio_read32(bar + NVME_REG_PMREBS); + pmrswtp = mmio_read32(bar + NVME_REG_PMRSWTP); + pmrmscl = mmio_read32(bar + NVME_REG_PMRMSCL); + pmrmscu = mmio_read32(bar + NVME_REG_PMRMSCU); + + if (human) { + if (cap != 0xffffffff) { + printf("cap : %"PRIx64"\n", cap); + stdout_registers_cap((struct nvme_bar_cap *)&cap); + } + if (vs != 0xffffffff) { + printf("version : %x\n", vs); + stdout_registers_version(vs); + } + if (cc != 0xffffffff) { + printf("cc : %x\n", cc); + stdout_registers_cc(cc); + } + if (csts != 0xffffffff) { + printf("csts : %x\n", csts); + stdout_registers_csts(csts); + } + if (nssr != 0xffffffff) { + printf("nssr : %x\n", nssr); + printf("\tNVM Subsystem Reset Control (NSSRC): %u\n\n", + nssr); + } + if (crto != 0xffffffff) { + printf("crto : %x\n", crto); + stdout_registers_crto(crto); + } + if (!fabrics) { + printf("intms : %x\n", intms); + printf("\tInterrupt Vector Mask Set (IVMS): %x\n\n", + intms); + + printf("intmc : %x\n", intmc); + printf("\tInterrupt Vector Mask Clear (IVMC): %x\n\n", + intmc); + printf("aqa : %x\n", aqa); + stdout_registers_aqa(aqa); + + printf("asq : %"PRIx64"\n", asq); + printf("\tAdmin Submission Queue Base (ASQB): %"PRIx64"\n\n", + asq); + + printf("acq : %"PRIx64"\n", acq); + printf("\tAdmin Completion Queue Base (ACQB): %"PRIx64"\n\n", + acq); + + printf("cmbloc : %x\n", cmbloc); + stdout_registers_cmbloc(cmbloc, cmbsz); + + printf("cmbsz : %x\n", cmbsz); + stdout_registers_cmbsz(cmbsz); + + printf("bpinfo : %x\n", bpinfo); + stdout_registers_bpinfo(bpinfo); + + printf("bprsel : %x\n", bprsel); + stdout_registers_bprsel(bprsel); + + printf("bpmbl : %"PRIx64"\n", bpmbl); + stdout_registers_bpmbl(bpmbl); + + printf("cmbmsc : %"PRIx64"\n", cmbmsc); + stdout_registers_cmbmsc(cmbmsc); + + printf("cmbsts : %x\n", cmbsts); + stdout_registers_cmbsts(cmbsts); + + printf("pmrcap : %x\n", pmrcap); + stdout_registers_pmrcap(pmrcap); + + printf("pmrctl : %x\n", pmrctl); + stdout_registers_pmrctl(pmrctl); + + printf("pmrsts : %x\n", pmrsts); + stdout_registers_pmrsts(pmrsts, pmrctl); + + printf("pmrebs : %x\n", pmrebs); + stdout_registers_pmrebs(pmrebs); + + printf("pmrswtp : %x\n", pmrswtp); + stdout_registers_pmrswtp(pmrswtp); + + printf("pmrmscl : %#x\n", pmrmscl); + stdout_registers_pmrmscl(pmrmscl); + + printf("pmrmscu : %#x\n", pmrmscu); + stdout_registers_pmrmscu(pmrmscu); + } + } else { + if (cap != 0xffffffff) + printf("cap : %"PRIx64"\n", cap); + if (vs != 0xffffffff) + printf("version : %x\n", vs); + if (cc != 0xffffffff) + printf("cc : %x\n", cc); + if (csts != 0xffffffff) + printf("csts : %x\n", csts); + if (nssr != 0xffffffff) + printf("nssr : %x\n", nssr); + if (crto != 0xffffffff) + printf("crto : %x\n", crto); + if (!fabrics) { + printf("intms : %x\n", intms); + printf("intmc : %x\n", intmc); + printf("aqa : %x\n", aqa); + printf("asq : %"PRIx64"\n", asq); + printf("acq : %"PRIx64"\n", acq); + printf("cmbloc : %x\n", cmbloc); + printf("cmbsz : %x\n", cmbsz); + printf("bpinfo : %x\n", bpinfo); + printf("bprsel : %x\n", bprsel); + printf("bpmbl : %"PRIx64"\n", bpmbl); + printf("cmbmsc : %"PRIx64"\n", cmbmsc); + printf("cmbsts : %x\n", cmbsts); + printf("pmrcap : %x\n", pmrcap); + printf("pmrctl : %x\n", pmrctl); + printf("pmrsts : %x\n", pmrsts); + printf("pmrebs : %x\n", pmrebs); + printf("pmrswtp : %x\n", pmrswtp); + printf("pmrmscl : %#x\n", pmrmscl); + printf("pmrmscu : %#x\n", pmrmscu); + } + } +} + +static void stdout_single_property(int offset, uint64_t value64) +{ + int human = stdout_print_ops.flags & VERBOSE; + + uint32_t value32; + + if (!human) { + if (nvme_is_64bit_reg(offset)) + printf("property: 0x%02x (%s), value: %"PRIx64"\n", + offset, nvme_register_to_string(offset), + value64); + else + printf("property: 0x%02x (%s), value: %x\n", offset, + nvme_register_to_string(offset), + (uint32_t) value64); + + return; + } + + value32 = (uint32_t) value64; + + switch (offset) { + case NVME_REG_CAP: + printf("cap : %"PRIx64"\n", value64); + stdout_registers_cap((struct nvme_bar_cap *)&value64); + break; + + case NVME_REG_VS: + printf("version : %x\n", value32); + stdout_registers_version(value32); + break; + + case NVME_REG_CC: + printf("cc : %x\n", value32); + stdout_registers_cc(value32); + break; + + case NVME_REG_CSTS: + printf("csts : %x\n", value32); + stdout_registers_csts(value32); + break; + + case NVME_REG_NSSR: + printf("nssr : %x\n", value32); + printf("\tNVM Subsystem Reset Control (NSSRC): %u\n\n", + value32); + break; + + case NVME_REG_CRTO: + printf("crto : %x\n", value32); + stdout_registers_crto(value32); + break; + + default: + printf("unknown property: 0x%02x (%s), value: %"PRIx64"\n", + offset, nvme_register_to_string(offset), value64); + break; + } +} + +static void stdout_status(int status) +{ + int val; + int type; + + /* + * Callers should be checking for negative values first, but provide a + * sensible fallback anyway + */ + if (status < 0) { + fprintf(stderr, "Error: %s\n", nvme_strerror(errno)); + return; + } + + val = nvme_status_get_value(status); + type = nvme_status_get_type(status); + + switch (type) { + case NVME_STATUS_TYPE_NVME: + fprintf(stderr, "NVMe status: %s(%#x)\n", + nvme_status_to_string(val, false), val); + break; + case NVME_STATUS_TYPE_MI: + fprintf(stderr, "NVMe-MI status: %s(%#x)\n", + nvme_mi_status_to_string(val), val); + break; + default: + fprintf(stderr, "Unknown status type %d, value %#x\n", type, + val); + break; + } +} + +static void stdout_id_ctrl_cmic(__u8 cmic) +{ + __u8 rsvd = (cmic & 0xF0) >> 4; + __u8 ana = (cmic & 0x8) >> 3; + __u8 sriov = (cmic & 0x4) >> 2; + __u8 mctl = (cmic & 0x2) >> 1; + __u8 mp = cmic & 0x1; + + if (rsvd) + printf(" [7:4] : %#x\tReserved\n", rsvd); + printf(" [3:3] : %#x\tANA %ssupported\n", ana, ana ? "" : "not "); + printf(" [2:2] : %#x\t%s\n", sriov, sriov ? "SR-IOV" : "PCI"); + printf(" [1:1] : %#x\t%s Controller\n", + mctl, mctl ? "Multi" : "Single"); + printf(" [0:0] : %#x\t%s Port\n", mp, mp ? "Multi" : "Single"); + printf("\n"); +} + +static void stdout_id_ctrl_oaes(__le32 ctrl_oaes) +{ + __u32 oaes = le32_to_cpu(ctrl_oaes); + __u32 disc = (oaes >> 31) & 0x1; + __u32 rsvd0 = (oaes & 0x70000000) >> 28; + __u32 zicn = (oaes & 0x08000000) >> 27; + __u32 rsvd1 = (oaes & 0x07FF0000) >> 16; + __u32 normal_shn = (oaes >> 15) & 0x1; + __u32 egealpcn = (oaes & 0x4000) >> 14; + __u32 lbasin = (oaes & 0x2000) >> 13; + __u32 plealcn = (oaes & 0x1000) >> 12; + __u32 anacn = (oaes & 0x800) >> 11; + __u32 rsvd2 = (oaes >> 10) & 0x1; + __u32 fan = (oaes & 0x200) >> 9; + __u32 nace = (oaes & 0x100) >> 8; + __u32 rsvd3 = oaes & 0xFF; + + printf(" [31:31] : %#x\tDiscovery Log Change Notice %sSupported\n", + disc, disc ? "" : "Not "); + if (rsvd0) + printf(" [30:28] : %#x\tReserved\n", rsvd0); + printf(" [27:27] : %#x\tZone Descriptor Changed Notices %sSupported\n", + zicn, zicn ? "" : "Not "); + if (rsvd1) + printf(" [26:16] : %#x\tReserved\n", rsvd1); + printf(" [15:15] : %#x\tNormal NSS Shutdown Event %sSupported\n", + normal_shn, normal_shn ? "" : "Not "); + printf(" [14:14] : %#x\tEndurance Group Event Aggregate Log Page"\ + " Change Notice %sSupported\n", + egealpcn, egealpcn ? "" : "Not "); + printf(" [13:13] : %#x\tLBA Status Information Notices %sSupported\n", + lbasin, lbasin ? "" : "Not "); + printf(" [12:12] : %#x\tPredictable Latency Event Aggregate Log Change"\ + " Notices %sSupported\n", + plealcn, plealcn ? "" : "Not "); + printf(" [11:11] : %#x\tAsymmetric Namespace Access Change Notices"\ + " %sSupported\n", anacn, anacn ? "" : "Not "); + if (rsvd2) + printf(" [10:10] : %#x\tReserved\n", rsvd2); + printf(" [9:9] : %#x\tFirmware Activation Notices %sSupported\n", + fan, fan ? "" : "Not "); + printf(" [8:8] : %#x\tNamespace Attribute Changed Event %sSupported\n", + nace, nace ? "" : "Not "); + if (rsvd3) + printf(" [7:0] : %#x\tReserved\n", rsvd3); + printf("\n"); +} + +static void stdout_id_ctrl_ctratt(__le32 ctrl_ctratt) +{ + __u32 ctratt = le32_to_cpu(ctrl_ctratt); + __u32 rsvd20 = (ctratt >> 20); + __u32 fdps = (ctratt >> 19) & 0x1; + __u32 rsvd16 = (ctratt >> 16) & 0x7; + __u32 elbas = (ctratt >> 15) & 0x1; + __u32 delnvmset = (ctratt >> 14) & 0x1; + __u32 delegrp = (ctratt >> 13) & 0x1; + __u32 vcap = (ctratt >> 12) & 0x1; + __u32 fcap = (ctratt >> 11) & 0x1; + __u32 mds = (ctratt >> 10) & 0x1; + __u32 hostid128 = (ctratt & NVME_CTRL_CTRATT_128_ID) >> 0; + __u32 psp = (ctratt & NVME_CTRL_CTRATT_NON_OP_PSP) >> 1; + __u32 sets = (ctratt & NVME_CTRL_CTRATT_NVM_SETS) >> 2; + __u32 rrl = (ctratt & NVME_CTRL_CTRATT_READ_RECV_LVLS) >> 3; + __u32 eg = (ctratt & NVME_CTRL_CTRATT_ENDURANCE_GROUPS) >> 4; + __u32 iod = (ctratt & NVME_CTRL_CTRATT_PREDICTABLE_LAT) >> 5; + __u32 tbkas = (ctratt & NVME_CTRL_CTRATT_TBKAS) >> 6; + __u32 ng = (ctratt & NVME_CTRL_CTRATT_NAMESPACE_GRANULARITY) >> 7; + __u32 sqa = (ctratt & NVME_CTRL_CTRATT_SQ_ASSOCIATIONS) >> 8; + __u32 uuidlist = (ctratt & NVME_CTRL_CTRATT_UUID_LIST) >> 9; + + if (rsvd20) + printf(" [31:20] : %#x\tReserved\n", rsvd20); + printf(" [19:19] : %#x\tFlexible Data Placement %sSupported\n", + fdps, fdps ? "" : "Not "); + if (rsvd16) + printf(" [18:16] : %#x\tReserved\n", rsvd16); + printf(" [15:15] : %#x\tExtended LBA Formats %sSupported\n", + elbas, elbas ? "" : "Not "); + printf(" [14:14] : %#x\tDelete NVM Set %sSupported\n", + delnvmset, delnvmset ? "" : "Not "); + printf(" [13:13] : %#x\tDelete Endurance Group %sSupported\n", + delegrp, delegrp ? "" : "Not "); + printf(" [12:12] : %#x\tVariable Capacity Management %sSupported\n", + vcap, vcap ? "" : "Not "); + printf(" [11:11] : %#x\tFixed Capacity Management %sSupported\n", + fcap, fcap ? "" : "Not "); + printf(" [10:10] : %#x\tMulti Domain Subsystem %sSupported\n", + mds, mds ? "" : "Not "); + printf(" [9:9] : %#x\tUUID List %sSupported\n", + uuidlist, uuidlist ? "" : "Not "); + printf(" [8:8] : %#x\tSQ Associations %sSupported\n", + sqa, sqa ? "" : "Not "); + printf(" [7:7] : %#x\tNamespace Granularity %sSupported\n", + ng, ng ? "" : "Not "); + printf(" [6:6] : %#x\tTraffic Based Keep Alive %sSupported\n", + tbkas, tbkas ? "" : "Not "); + printf(" [5:5] : %#x\tPredictable Latency Mode %sSupported\n", + iod, iod ? "" : "Not "); + printf(" [4:4] : %#x\tEndurance Groups %sSupported\n", + eg, eg ? "" : "Not "); + printf(" [3:3] : %#x\tRead Recovery Levels %sSupported\n", + rrl, rrl ? "" : "Not "); + printf(" [2:2] : %#x\tNVM Sets %sSupported\n", + sets, sets ? "" : "Not "); + printf(" [1:1] : %#x\tNon-Operational Power State Permissive %sSupported\n", + psp, psp ? "" : "Not "); + printf(" [0:0] : %#x\t128-bit Host Identifier %sSupported\n", + hostid128, hostid128 ? "" : "Not "); + printf("\n"); +} + +static void stdout_id_ctrl_cntrltype(__u8 cntrltype) +{ + __u8 rsvd = (cntrltype & 0xFC) >> 2; + __u8 cntrl = cntrltype & 0x3; + + static const char *type[] = { + "Controller type not reported", + "I/O Controller", + "Discovery Controller", + "Administrative Controller" + }; + + printf(" [7:2] : %#x\tReserved\n", rsvd); + printf(" [1:0] : %#x\t%s\n", cntrltype, type[cntrl]); +} + +static void stdout_id_ctrl_nvmsr(__u8 nvmsr) +{ + __u8 rsvd = (nvmsr >> 2) & 0xfc; + __u8 nvmee = (nvmsr >> 1) & 0x1; + __u8 nvmesd = nvmsr & 0x1; + + if (rsvd) + printf(" [7:2] : %#x\tReserved\n", rsvd); + printf(" [1:1] : %#x\tNVM subsystem %spart of an Enclosure\n", + nvmee, nvmee ? "" : "Not "); + printf(" [0:0] : %#x\tNVM subsystem %spart of a Storage Device\n", + nvmesd, nvmesd ? "" : "Not "); + printf("\n"); +} + +static void stdout_id_ctrl_vwci(__u8 vwci) +{ + __u8 vwcrv = (vwci >> 7) & 0x1; + __u8 vwcr = vwci & 0xfe; + + printf(" [7:7] : %#x\tVPD Write Cycles Remaining field is %svalid.\n", + vwcrv, vwcrv ? "" : "Not "); + printf(" [6:0] : %#x\tVPD Write Cycles Remaining \n", vwcr); + printf("\n"); + +} + +static void stdout_id_ctrl_mec(__u8 mec) +{ + __u8 rsvd = (mec >> 2) & 0xfc; + __u8 pcieme = (mec >> 1) & 0x1; + __u8 smbusme = mec & 0x1; + + if (rsvd) + printf(" [7:2] : %#x\tReserved\n", rsvd); + printf(" [1:1] : %#x\tNVM subsystem %scontains a Management Endpoint"\ + " on a PCIe port\n", pcieme, pcieme ? "" : "Not "); + printf(" [0:0] : %#x\tNVM subsystem %scontains a Management Endpoint"\ + " on an SMBus/I2C port\n", smbusme, smbusme ? "" : "Not "); + printf("\n"); + +} + +static void stdout_id_ctrl_oacs(__le16 ctrl_oacs) +{ + __u16 oacs = le16_to_cpu(ctrl_oacs); + __u16 rsvd = (oacs & 0xF800) >> 11; + __u16 lock = (oacs >> 10) & 0x1; + __u16 glbas = (oacs & 0x200) >> 9; + __u16 dbc = (oacs & 0x100) >> 8; + __u16 vir = (oacs & 0x80) >> 7; + __u16 nmi = (oacs & 0x40) >> 6; + __u16 dir = (oacs & 0x20) >> 5; + __u16 sft = (oacs & 0x10) >> 4; + __u16 nsm = (oacs & 0x8) >> 3; + __u16 fwc = (oacs & 0x4) >> 2; + __u16 fmt = (oacs & 0x2) >> 1; + __u16 sec = oacs & 0x1; + + if (rsvd) + printf(" [15:11] : %#x\tReserved\n", rsvd); + printf(" [10:10] : %#x\tLockdown Command and Feature %sSupported\n", + lock, lock ? "" : "Not "); + printf(" [9:9] : %#x\tGet LBA Status Capability %sSupported\n", + glbas, glbas ? "" : "Not "); + printf(" [8:8] : %#x\tDoorbell Buffer Config %sSupported\n", + dbc, dbc ? "" : "Not "); + printf(" [7:7] : %#x\tVirtualization Management %sSupported\n", + vir, vir ? "" : "Not "); + printf(" [6:6] : %#x\tNVMe-MI Send and Receive %sSupported\n", + nmi, nmi ? "" : "Not "); + printf(" [5:5] : %#x\tDirectives %sSupported\n", + dir, dir ? "" : "Not "); + printf(" [4:4] : %#x\tDevice Self-test %sSupported\n", + sft, sft ? "" : "Not "); + printf(" [3:3] : %#x\tNS Management and Attachment %sSupported\n", + nsm, nsm ? "" : "Not "); + printf(" [2:2] : %#x\tFW Commit and Download %sSupported\n", + fwc, fwc ? "" : "Not "); + printf(" [1:1] : %#x\tFormat NVM %sSupported\n", + fmt, fmt ? "" : "Not "); + printf(" [0:0] : %#x\tSecurity Send and Receive %sSupported\n", + sec, sec ? "" : "Not "); + printf("\n"); +} + +static void stdout_id_ctrl_frmw(__u8 frmw) +{ + __u8 rsvd = (frmw & 0xC0) >> 6; + __u8 smud = (frmw >> 5) & 0x1; + __u8 fawr = (frmw & 0x10) >> 4; + __u8 nfws = (frmw & 0xE) >> 1; + __u8 s1ro = frmw & 0x1; + + if (rsvd) + printf(" [7:6] : %#x\tReserved\n", rsvd); + printf(" [5:5] : %#x\tMultiple FW or Boot Update Detection %sSupported\n", + smud, smud ? "" : "Not "); + printf(" [4:4] : %#x\tFirmware Activate Without Reset %sSupported\n", + fawr, fawr ? "" : "Not "); + printf(" [3:1] : %#x\tNumber of Firmware Slots\n", nfws); + printf(" [0:0] : %#x\tFirmware Slot 1 Read%s\n", + s1ro, s1ro ? "-Only" : "/Write"); + printf("\n"); +} + +static void stdout_id_ctrl_lpa(__u8 lpa) +{ + __u8 rsvd = (lpa & 0x80) >> 7; + __u8 tel = (lpa >> 6) & 0x1; + __u8 lid_sup = (lpa >> 5) & 0x1; + __u8 persevnt = (lpa & 0x10) >> 4; + __u8 telem = (lpa & 0x8) >> 3; + __u8 ed = (lpa & 0x4) >> 2; + __u8 celp = (lpa & 0x2) >> 1; + __u8 smlp = lpa & 0x1; + + if (rsvd) + printf(" [7:7] : %#x\tReserved\n", rsvd); + printf(" [6:6] : %#x\tTelemetry Log Data Area 4 %sSupported\n", + tel, tel ? "" : "Not "); + printf(" [5:5] : %#x\tLID 0x0, Scope of each command in LID 0x5, "\ + "0x12, 0x13 %sSupported\n", lid_sup, lid_sup ? "" : "Not "); + printf(" [4:4] : %#x\tPersistent Event log %sSupported\n", + persevnt, persevnt ? "" : "Not "); + printf(" [3:3] : %#x\tTelemetry host/controller initiated log page %sSupported\n", + telem, telem ? "" : "Not "); + printf(" [2:2] : %#x\tExtended data for Get Log Page %sSupported\n", + ed, ed ? "" : "Not "); + printf(" [1:1] : %#x\tCommand Effects Log Page %sSupported\n", + celp, celp ? "" : "Not "); + printf(" [0:0] : %#x\tSMART/Health Log Page per NS %sSupported\n", + smlp, smlp ? "" : "Not "); + printf("\n"); +} + +static void stdout_id_ctrl_elpe(__u8 elpe) +{ + printf(" [7:0] : %d (0's based)\tError Log Page Entries (ELPE)\n", + elpe); + printf("\n"); +} + +static void stdout_id_ctrl_npss(__u8 npss) +{ + printf(" [7:0] : %d (0's based)\tNumber of Power States Support (NPSS)\n", + npss); + printf("\n"); +} + +static void stdout_id_ctrl_avscc(__u8 avscc) +{ + __u8 rsvd = (avscc & 0xFE) >> 1; + __u8 fmt = avscc & 0x1; + if (rsvd) + printf(" [7:1] : %#x\tReserved\n", rsvd); + printf(" [0:0] : %#x\tAdmin Vendor Specific Commands uses %s Format\n", + fmt, fmt ? "NVMe" : "Vendor Specific"); + printf("\n"); +} + +static void stdout_id_ctrl_apsta(__u8 apsta) +{ + __u8 rsvd = (apsta & 0xFE) >> 1; + __u8 apst = apsta & 0x1; + if (rsvd) + printf(" [7:1] : %#x\tReserved\n", rsvd); + printf(" [0:0] : %#x\tAutonomous Power State Transitions %sSupported\n", + apst, apst ? "" : "Not "); + printf("\n"); +} + +static void stdout_id_ctrl_wctemp(__le16 wctemp) +{ + printf(" [15:0] : %ld °C (%u K)\tWarning Composite Temperature Threshold (WCTEMP)\n", + kelvin_to_celsius(le16_to_cpu(wctemp)), le16_to_cpu(wctemp)); + printf("\n"); +} + +static void stdout_id_ctrl_cctemp(__le16 cctemp) +{ + printf(" [15:0] : %ld °C (%u K)\tCritical Composite Temperature Threshold (CCTEMP)\n", + kelvin_to_celsius(le16_to_cpu(cctemp)), le16_to_cpu(cctemp)); + printf("\n"); +} + +static void stdout_id_ctrl_tnvmcap(__u8 *tnvmcap) +{ + printf("[127:0] : %s\n", uint128_t_to_l10n_string(le128_to_cpu(tnvmcap))); + printf("\tTotal NVM Capacity (TNVMCAP)\n\n"); +} + +static void stdout_id_ctrl_unvmcap(__u8 *unvmcap) +{ + printf("[127:0] : %s\n", uint128_t_to_l10n_string(le128_to_cpu(unvmcap))); + printf("\tUnallocated NVM Capacity (UNVMCAP)\n\n"); +} + +void stdout_id_ctrl_rpmbs(__le32 ctrl_rpmbs) +{ + __u32 rpmbs = le32_to_cpu(ctrl_rpmbs); + __u32 asz = (rpmbs & 0xFF000000) >> 24; + __u32 tsz = (rpmbs & 0xFF0000) >> 16; + __u32 rsvd = (rpmbs & 0xFFC0) >> 6; + __u32 auth = (rpmbs & 0x38) >> 3; + __u32 rpmb = rpmbs & 0x7; + + printf(" [31:24]: %#x\tAccess Size\n", asz); + printf(" [23:16]: %#x\tTotal Size\n", tsz); + if (rsvd) + printf(" [15:6] : %#x\tReserved\n", rsvd); + printf(" [5:3] : %#x\tAuthentication Method\n", auth); + printf(" [2:0] : %#x\tNumber of RPMB Units\n", rpmb); + printf("\n"); +} + +static void stdout_id_ctrl_hctma(__le16 ctrl_hctma) +{ + __u16 hctma = le16_to_cpu(ctrl_hctma); + __u16 rsvd = (hctma & 0xFFFE) >> 1; + __u16 hctm = hctma & 0x1; + + if (rsvd) + printf(" [15:1] : %#x\tReserved\n", rsvd); + printf(" [0:0] : %#x\tHost Controlled Thermal Management %sSupported\n", + hctm, hctm ? "" : "Not "); + printf("\n"); +} + +static void stdout_id_ctrl_mntmt(__le16 mntmt) +{ + printf(" [15:0] : %ld °C (%u K)\tMinimum Thermal Management Temperature (MNTMT)\n", + kelvin_to_celsius(le16_to_cpu(mntmt)), le16_to_cpu(mntmt)); + printf("\n"); +} + +static void stdout_id_ctrl_mxtmt(__le16 mxtmt) +{ + printf(" [15:0] : %ld °C (%u K)\tMaximum Thermal Management Temperature (MXTMT)\n", + kelvin_to_celsius(le16_to_cpu(mxtmt)), le16_to_cpu(mxtmt)); + printf("\n"); +} + +static void stdout_id_ctrl_sanicap(__le32 ctrl_sanicap) +{ + __u32 sanicap = le32_to_cpu(ctrl_sanicap); + __u32 rsvd = (sanicap & 0x1FFFFFF8) >> 3; + __u32 owr = (sanicap & 0x4) >> 2; + __u32 ber = (sanicap & 0x2) >> 1; + __u32 cer = sanicap & 0x1; + __u32 ndi = (sanicap & 0x20000000) >> 29; + __u32 nodmmas = (sanicap & 0xC0000000) >> 30; + + static const char *modifies_media[] = { + "Additional media modification after sanitize operation completes successfully is not defined", + "Media is not additionally modified after sanitize operation completes successfully", + "Media is additionally modified after sanitize operation completes successfully", + "Reserved" + }; + + printf(" [31:30] : %#x\t%s\n", nodmmas, modifies_media[nodmmas]); + printf(" [29:29] : %#x\tNo-Deallocate After Sanitize bit in Sanitize command %sSupported\n", + ndi, ndi ? "Not " : ""); + if (rsvd) + printf(" [28:3] : %#x\tReserved\n", rsvd); + printf(" [2:2] : %#x\tOverwrite Sanitize Operation %sSupported\n", + owr, owr ? "" : "Not "); + printf(" [1:1] : %#x\tBlock Erase Sanitize Operation %sSupported\n", + ber, ber ? "" : "Not "); + printf(" [0:0] : %#x\tCrypto Erase Sanitize Operation %sSupported\n", + cer, cer ? "" : "Not "); + printf("\n"); +} + +static void stdout_id_ctrl_anacap(__u8 anacap) +{ + __u8 nz = (anacap & 0x80) >> 7; + __u8 grpid_static = (anacap & 0x40) >> 6; + __u8 rsvd = (anacap & 0x20) >> 5; + __u8 ana_change = (anacap & 0x10) >> 4; + __u8 ana_persist_loss = (anacap & 0x08) >> 3; + __u8 ana_inaccessible = (anacap & 0x04) >> 2; + __u8 ana_nonopt = (anacap & 0x02) >> 1; + __u8 ana_opt = (anacap & 0x01); + + printf(" [7:7] : %#x\tNon-zero group ID %sSupported\n", + nz, nz ? "" : "Not "); + printf(" [6:6] : %#x\tGroup ID does %schange\n", + grpid_static, grpid_static ? "not " : ""); + if (rsvd) + printf(" [5:5] : %#x\tReserved\n", rsvd); + printf(" [4:4] : %#x\tANA Change state %sSupported\n", + ana_change, ana_change ? "" : "Not "); + printf(" [3:3] : %#x\tANA Persistent Loss state %sSupported\n", + ana_persist_loss, ana_persist_loss ? "" : "Not "); + printf(" [2:2] : %#x\tANA Inaccessible state %sSupported\n", + ana_inaccessible, ana_inaccessible ? "" : "Not "); + printf(" [1:1] : %#x\tANA Non-optimized state %sSupported\n", + ana_nonopt, ana_nonopt ? "" : "Not "); + printf(" [0:0] : %#x\tANA Optimized state %sSupported\n", + ana_opt, ana_opt ? "" : "Not "); + printf("\n"); +} + +static void stdout_id_ctrl_sqes(__u8 sqes) +{ + __u8 msqes = (sqes & 0xF0) >> 4; + __u8 rsqes = sqes & 0xF; + printf(" [7:4] : %#x\tMax SQ Entry Size (%d)\n", msqes, 1 << msqes); + printf(" [3:0] : %#x\tMin SQ Entry Size (%d)\n", rsqes, 1 << rsqes); + printf("\n"); +} + +static void stdout_id_ctrl_cqes(__u8 cqes) +{ + __u8 mcqes = (cqes & 0xF0) >> 4; + __u8 rcqes = cqes & 0xF; + printf(" [7:4] : %#x\tMax CQ Entry Size (%d)\n", mcqes, 1 << mcqes); + printf(" [3:0] : %#x\tMin CQ Entry Size (%d)\n", rcqes, 1 << rcqes); + printf("\n"); +} + +static void stdout_id_ctrl_oncs(__le16 ctrl_oncs) +{ + __u16 oncs = le16_to_cpu(ctrl_oncs); + __u16 rsvd = (oncs & 0xFE00) >> 9; + __u16 copy = (oncs & 0x100) >> 8; + __u16 vrfy = (oncs & 0x80) >> 7; + __u16 tmst = (oncs & 0x40) >> 6; + __u16 resv = (oncs & 0x20) >> 5; + __u16 save = (oncs & 0x10) >> 4; + __u16 wzro = (oncs & 0x8) >> 3; + __u16 dsms = (oncs & 0x4) >> 2; + __u16 wunc = (oncs & 0x2) >> 1; + __u16 cmp = oncs & 0x1; + + if (rsvd) + printf(" [15:9] : %#x\tReserved\n", rsvd); + printf(" [8:8] : %#x\tCopy %sSupported\n", + copy, copy ? "" : "Not "); + printf(" [7:7] : %#x\tVerify %sSupported\n", + vrfy, vrfy ? "" : "Not "); + printf(" [6:6] : %#x\tTimestamp %sSupported\n", + tmst, tmst ? "" : "Not "); + printf(" [5:5] : %#x\tReservations %sSupported\n", + resv, resv ? "" : "Not "); + printf(" [4:4] : %#x\tSave and Select %sSupported\n", + save, save ? "" : "Not "); + printf(" [3:3] : %#x\tWrite Zeroes %sSupported\n", + wzro, wzro ? "" : "Not "); + printf(" [2:2] : %#x\tData Set Management %sSupported\n", + dsms, dsms ? "" : "Not "); + printf(" [1:1] : %#x\tWrite Uncorrectable %sSupported\n", + wunc, wunc ? "" : "Not "); + printf(" [0:0] : %#x\tCompare %sSupported\n", + cmp, cmp ? "" : "Not "); + printf("\n"); +} + +static void stdout_id_ctrl_fuses(__le16 ctrl_fuses) +{ + __u16 fuses = le16_to_cpu(ctrl_fuses); + __u16 rsvd = (fuses & 0xFE) >> 1; + __u16 cmpw = fuses & 0x1; + + if (rsvd) + printf(" [15:1] : %#x\tReserved\n", rsvd); + printf(" [0:0] : %#x\tFused Compare and Write %sSupported\n", + cmpw, cmpw ? "" : "Not "); + printf("\n"); +} + +static void stdout_id_ctrl_fna(__u8 fna) +{ + __u8 rsvd = (fna & 0xF0) >> 4; + __u8 bcnsid = (fna & 0x8) >> 3; + __u8 cese = (fna & 0x4) >> 2; + __u8 cens = (fna & 0x2) >> 1; + __u8 fmns = fna & 0x1; + if (rsvd) + printf(" [7:4] : %#x\tReserved\n", rsvd); + printf(" [3:3] : %#x\tFormat NVM Broadcast NSID (FFFFFFFFh) %sSupported\n", + bcnsid, bcnsid ? "Not " : ""); + printf(" [2:2] : %#x\tCrypto Erase %sSupported as part of Secure Erase\n", + cese, cese ? "" : "Not "); + printf(" [1:1] : %#x\tCrypto Erase Applies to %s Namespace(s)\n", + cens, cens ? "All" : "Single"); + printf(" [0:0] : %#x\tFormat Applies to %s Namespace(s)\n", + fmns, fmns ? "All" : "Single"); + printf("\n"); +} + +static void stdout_id_ctrl_vwc(__u8 vwc) +{ + __u8 rsvd = (vwc & 0xF8) >> 3; + __u8 flush = (vwc & 0x6) >> 1; + __u8 vwcp = vwc & 0x1; + + static const char *flush_behavior[] = { + "Support for the NSID field set to FFFFFFFFh is not indicated", + "Reserved", + "The Flush command does not support NSID set to FFFFFFFFh", + "The Flush command supports NSID set to FFFFFFFFh" + }; + + if (rsvd) + printf(" [7:3] : %#x\tReserved\n", rsvd); + printf(" [2:1] : %#x\t%s\n", flush, flush_behavior[flush]); + printf(" [0:0] : %#x\tVolatile Write Cache %sPresent\n", + vwcp, vwcp ? "" : "Not "); + printf("\n"); +} + +static void stdout_id_ctrl_icsvscc(__u8 icsvscc) +{ + __u8 rsvd = (icsvscc & 0xFE) >> 1; + __u8 fmt = icsvscc & 0x1; + if (rsvd) + printf(" [7:1] : %#x\tReserved\n", rsvd); + printf(" [0:0] : %#x\tNVM Vendor Specific Commands uses %s Format\n", + fmt, fmt ? "NVMe" : "Vendor Specific"); + printf("\n"); +} + +static void stdout_id_ctrl_nwpc(__u8 nwpc) +{ + __u8 no_wp_wp = (nwpc & 0x01); + __u8 wp_power_cycle = (nwpc & 0x02) >> 1; + __u8 wp_permanent = (nwpc & 0x04) >> 2; + __u8 rsvd = (nwpc & 0xF8) >> 3; + + if (rsvd) + printf(" [7:3] : %#x\tReserved\n", rsvd); + + printf(" [2:2] : %#x\tPermanent Write Protect %sSupported\n", + wp_permanent, wp_permanent ? "" : "Not "); + printf(" [1:1] : %#x\tWrite Protect Until Power Supply %sSupported\n", + wp_power_cycle, wp_power_cycle ? "" : "Not "); + printf(" [0:0] : %#x\tNo Write Protect and Write Protect Namespace %sSupported\n", + no_wp_wp, no_wp_wp ? "" : "Not "); + printf("\n"); +} + +static void stdout_id_ctrl_ocfs(__le16 ctrl_ocfs) +{ + __u16 ocfs = le16_to_cpu(ctrl_ocfs); + __u16 rsvd = (ocfs & 0xfffc) >> 2; + __u8 copy_fmt_1 = (ocfs >> 1) & 0x1; + __u8 copy_fmt_0 = ocfs & 0x1; + if (rsvd) + printf(" [15:2] : %#x\tReserved\n", rsvd); + printf(" [1:1] : %#x\tController Copy Format 1h %sSupported\n", + copy_fmt_1, copy_fmt_1 ? "" : "Not "); + printf(" [0:0] : %#x\tController Copy Format 0h %sSupported\n", + copy_fmt_0, copy_fmt_0 ? "" : "Not "); + printf("\n"); +} + +static void stdout_id_ctrl_sgls(__le32 ctrl_sgls) +{ + __u32 sgls = le32_to_cpu(ctrl_sgls); + __u32 rsvd0 = (sgls & 0xFFC00000) >> 22; + __u32 trsdbd = (sgls & 0x200000) >> 21; + __u32 aofdsl = (sgls & 0x100000) >> 20; + __u32 mpcsd = (sgls & 0x80000) >> 19; + __u32 sglltb = (sgls & 0x40000) >> 18; + __u32 bacmdb = (sgls & 0x20000) >> 17; + __u32 bbs = (sgls & 0x10000) >> 16; + __u32 sdt = (sgls >> 8) & 0xff; + __u32 rsvd1 = (sgls & 0xF8) >> 3; + __u32 key = (sgls & 0x4) >> 2; + __u32 sglsp = sgls & 0x3; + + if (rsvd0) + printf(" [31:22]: %#x\tReserved\n", rsvd0); + if (sglsp || (!sglsp && trsdbd)) + printf(" [21:21]: %#x\tTransport SGL Data Block Descriptor %sSupported\n", + trsdbd, trsdbd ? "" : "Not "); + if (sglsp || (!sglsp && aofdsl)) + printf(" [20:20]: %#x\tAddress Offsets %sSupported\n", + aofdsl, aofdsl ? "" : "Not "); + if (sglsp || (!sglsp && mpcsd)) + printf(" [19:19]: %#x\tMetadata Pointer Containing " + "SGL Descriptor is %sSupported\n", + mpcsd, mpcsd ? "" : "Not "); + if (sglsp || (!sglsp && sglltb)) + printf(" [18:18]: %#x\tSGL Length Larger than Buffer %sSupported\n", + sglltb, sglltb ? "" : "Not "); + if (sglsp || (!sglsp && bacmdb)) + printf(" [17:17]: %#x\tByte-Aligned Contig. MD Buffer %sSupported\n", + bacmdb, bacmdb ? "" : "Not "); + if (sglsp || (!sglsp && bbs)) + printf(" [16:16]: %#x\tSGL Bit-Bucket %sSupported\n", + bbs, bbs ? "" : "Not "); + printf(" [15:8] : %#x\tSGL Descriptor Threshold\n", sdt); + if (rsvd1) + printf(" [7:3] : %#x\tReserved\n", rsvd1); + if (sglsp || (!sglsp && key)) + printf(" [2:2] : %#x\tKeyed SGL Data Block descriptor %sSupported\n", + key, key ? "" : "Not "); + if (sglsp == 0x3) + printf(" [1:0] : %#x\tReserved\n", sglsp); + else if (sglsp == 0x2) + printf(" [1:0] : %#x\tScatter-Gather Lists Supported." + " Dword alignment required.\n", sglsp); + else if (sglsp == 0x1) + printf(" [1:0] : %#x\tScatter-Gather Lists Supported." + " No Dword alignment required.\n", sglsp); + else + printf(" [1:0] : %#x\tScatter-Gather Lists Not Supported\n", sglsp); + printf("\n"); +} + +static void stdout_id_ctrl_fcatt(__u8 fcatt) +{ + __u8 rsvd = (fcatt & 0xFE) >> 1; + __u8 scm = fcatt & 0x1; + if (rsvd) + printf(" [7:1] : %#x\tReserved\n", rsvd); + printf(" [0:0] : %#x\t%s Controller Model\n", + scm, scm ? "Static" : "Dynamic"); + printf("\n"); +} + +static void stdout_id_ctrl_ofcs(__le16 ofcs) +{ + __u16 rsvd = (ofcs & 0xfffe) >> 1; + __u8 disconn = ofcs & 0x1; + if (rsvd) + printf(" [15:1] : %#x\tReserved\n", rsvd); + printf(" [0:0] : %#x\tDisconnect command %s Supported\n", + disconn, disconn ? "" : "Not"); + printf("\n"); + +} + +static void stdout_id_ns_nsfeat(__u8 nsfeat) +{ + __u8 rsvd = (nsfeat & 0xE0) >> 5; + __u8 ioopt = (nsfeat & 0x10) >> 4; + __u8 uidreuse = (nsfeat & 0x8) >> 3; + __u8 dulbe = (nsfeat & 0x4) >> 2; + __u8 na = (nsfeat & 0x2) >> 1; + __u8 thin = nsfeat & 0x1; + if (rsvd) + printf(" [7:5] : %#x\tReserved\n", rsvd); + printf(" [4:4] : %#x\tNPWG, NPWA, NPDG, NPDA, and NOWS are %sSupported\n", + ioopt, ioopt ? "" : "Not "); + printf(" [3:3] : %#x\tNGUID and EUI64 fields if non-zero, %sReused\n", + uidreuse, uidreuse ? "Never " : ""); + printf(" [2:2] : %#x\tDeallocated or Unwritten Logical Block error %sSupported\n", + dulbe, dulbe ? "" : "Not "); + printf(" [1:1] : %#x\tNamespace uses %s\n", + na, na ? "NAWUN, NAWUPF, and NACWU" : "AWUN, AWUPF, and ACWU"); + printf(" [0:0] : %#x\tThin Provisioning %sSupported\n", + thin, thin ? "" : "Not "); + printf("\n"); +} + +static void stdout_id_ns_flbas(__u8 flbas) +{ + __u8 rsvd = (flbas & 0x80) >> 7; + __u8 msb2_lbaf = (flbas & NVME_NS_FLBAS_HIGHER_MASK) >> 5; + __u8 mdedata = (flbas & 0x10) >> 4; + __u8 lsb4_lbaf = flbas & NVME_NS_FLBAS_LOWER_MASK; + + if (rsvd) + printf(" [7:7] : %#x\tReserved\n", rsvd); + printf(" [6:5] : %#x\tMost significant 2 bits of Current LBA Format Selected\n", + msb2_lbaf); + printf(" [4:4] : %#x\tMetadata Transferred %s\n", + mdedata, mdedata ? "at End of Data LBA" : "in Separate Contiguous Buffer"); + printf(" [3:0] : %#x\tLeast significant 4 bits of Current LBA Format Selected\n", + lsb4_lbaf); + printf("\n"); +} + +static void stdout_id_ns_mc(__u8 mc) +{ + __u8 rsvd = (mc & 0xFC) >> 2; + __u8 mdp = (mc & 0x2) >> 1; + __u8 extdlba = mc & 0x1; + if (rsvd) + printf(" [7:2] : %#x\tReserved\n", rsvd); + printf(" [1:1] : %#x\tMetadata Pointer %sSupported\n", + mdp, mdp ? "" : "Not "); + printf(" [0:0] : %#x\tMetadata as Part of Extended Data LBA %sSupported\n", + extdlba, extdlba ? "" : "Not "); + printf("\n"); +} + +static void stdout_id_ns_dpc(__u8 dpc) +{ + __u8 rsvd = (dpc & 0xE0) >> 5; + __u8 pil8 = (dpc & 0x10) >> 4; + __u8 pif8 = (dpc & 0x8) >> 3; + __u8 pit3 = (dpc & 0x4) >> 2; + __u8 pit2 = (dpc & 0x2) >> 1; + __u8 pit1 = dpc & 0x1; + if (rsvd) + printf(" [7:5] : %#x\tReserved\n", rsvd); + printf(" [4:4] : %#x\tProtection Information Transferred as Last 8 Bytes of Metadata %sSupported\n", + pil8, pil8 ? "" : "Not "); + printf(" [3:3] : %#x\tProtection Information Transferred as First 8 Bytes of Metadata %sSupported\n", + pif8, pif8 ? "" : "Not "); + printf(" [2:2] : %#x\tProtection Information Type 3 %sSupported\n", + pit3, pit3 ? "" : "Not "); + printf(" [1:1] : %#x\tProtection Information Type 2 %sSupported\n", + pit2, pit2 ? "" : "Not "); + printf(" [0:0] : %#x\tProtection Information Type 1 %sSupported\n", + pit1, pit1 ? "" : "Not "); + printf("\n"); +} + +static void stdout_id_ns_dps(__u8 dps) +{ + __u8 rsvd = (dps & 0xF0) >> 4; + __u8 pif8 = (dps & 0x8) >> 3; + __u8 pit = dps & 0x7; + if (rsvd) + printf(" [7:4] : %#x\tReserved\n", rsvd); + printf(" [3:3] : %#x\tProtection Information is Transferred as %s 8 Bytes of Metadata\n", + pif8, pif8 ? "First" : "Last"); + printf(" [2:0] : %#x\tProtection Information %s\n", pit, + pit == 3 ? "Type 3 Enabled" : + pit == 2 ? "Type 2 Enabled" : + pit == 1 ? "Type 1 Enabled" : + pit == 0 ? "Disabled" : "Reserved Enabled"); + printf("\n"); +} + +static void stdout_id_ns_nmic(__u8 nmic) +{ + __u8 rsvd = (nmic & 0xFE) >> 1; + __u8 mp = nmic & 0x1; + if (rsvd) + printf(" [7:1] : %#x\tReserved\n", rsvd); + printf(" [0:0] : %#x\tNamespace Multipath %sCapable\n", + mp, mp ? "" : "Not "); + printf("\n"); +} + +static void stdout_id_ns_rescap(__u8 rescap) +{ + __u8 iekr = (rescap & 0x80) >> 7; + __u8 eaar = (rescap & 0x40) >> 6; + __u8 wear = (rescap & 0x20) >> 5; + __u8 earo = (rescap & 0x10) >> 4; + __u8 wero = (rescap & 0x8) >> 3; + __u8 ea = (rescap & 0x4) >> 2; + __u8 we = (rescap & 0x2) >> 1; + __u8 ptpl = rescap & 0x1; + + printf(" [7:7] : %#x\tIgnore Existing Key - Used as defined in revision %s\n", + iekr, iekr ? "1.3 or later" : "1.2.1 or earlier"); + printf(" [6:6] : %#x\tExclusive Access - All Registrants %sSupported\n", + eaar, eaar ? "" : "Not "); + printf(" [5:5] : %#x\tWrite Exclusive - All Registrants %sSupported\n", + wear, wear ? "" : "Not "); + printf(" [4:4] : %#x\tExclusive Access - Registrants Only %sSupported\n", + earo, earo ? "" : "Not "); + printf(" [3:3] : %#x\tWrite Exclusive - Registrants Only %sSupported\n", + wero, wero ? "" : "Not "); + printf(" [2:2] : %#x\tExclusive Access %sSupported\n", + ea, ea ? "" : "Not "); + printf(" [1:1] : %#x\tWrite Exclusive %sSupported\n", + we, we ? "" : "Not "); + printf(" [0:0] : %#x\tPersist Through Power Loss %sSupported\n", + ptpl, ptpl ? "" : "Not "); + printf("\n"); +} + +static void stdout_id_ns_fpi(__u8 fpi) +{ + __u8 fpis = (fpi & 0x80) >> 7; + __u8 fpii = fpi & 0x7F; + printf(" [7:7] : %#x\tFormat Progress Indicator %sSupported\n", + fpis, fpis ? "" : "Not "); + if (fpis || (!fpis && fpii)) + printf(" [6:0] : %#x\tFormat Progress Indicator (Remaining %d%%)\n", + fpii, fpii); + printf("\n"); +} + +static void stdout_id_ns_nsattr(__u8 nsattr) +{ + __u8 rsvd = (nsattr & 0xFE) >> 1; + __u8 write_protected = nsattr & 0x1; + if (rsvd) + printf(" [7:1] : %#x\tReserved\n", rsvd); + printf(" [0:0] : %#x\tNamespace %sWrite Protected\n", + write_protected, write_protected ? "" : "Not "); + printf("\n"); +} + +static void stdout_id_ns_dlfeat(__u8 dlfeat) +{ + __u8 rsvd = (dlfeat & 0xE0) >> 5; + __u8 guard = (dlfeat & 0x10) >> 4; + __u8 dwz = (dlfeat & 0x8) >> 3; + __u8 val = dlfeat & 0x7; + if (rsvd) + printf(" [7:5] : %#x\tReserved\n", rsvd); + printf(" [4:4] : %#x\tGuard Field of Deallocated Logical Blocks is set to %s\n", + guard, guard ? "CRC of The Value Read" : "0xFFFF"); + printf(" [3:3] : %#x\tDeallocate Bit in the Write Zeroes Command is %sSupported\n", + dwz, dwz ? "" : "Not "); + printf(" [2:0] : %#x\tBytes Read From a Deallocated Logical Block and its Metadata are %s\n", + val, val == 2 ? "0xFF" : + val == 1 ? "0x00" : + val == 0 ? "Not Reported" : "Reserved Value"); + printf("\n"); +} + +static void stdout_id_ns(struct nvme_id_ns *ns, unsigned int nsid, + unsigned int lba_index, bool cap_only) +{ + bool human = stdout_print_ops.flags & VERBOSE; + int vs = stdout_print_ops.flags & VS; + int i; + __u8 flbas; + char *in_use = "(in use)"; + + if (!cap_only) { + printf("NVME Identify Namespace %d:\n", nsid); + printf("nsze : %#"PRIx64"\n", le64_to_cpu(ns->nsze)); + printf("ncap : %#"PRIx64"\n", le64_to_cpu(ns->ncap)); + printf("nuse : %#"PRIx64"\n", le64_to_cpu(ns->nuse)); + printf("nsfeat : %#x\n", ns->nsfeat); + if (human) + stdout_id_ns_nsfeat(ns->nsfeat); + } else + printf("NVMe Identify Namespace for LBA format[%d]:\n", lba_index); + + printf("nlbaf : %d\n", ns->nlbaf); + if (!cap_only) { + printf("flbas : %#x\n", ns->flbas); + if (human) + stdout_id_ns_flbas(ns->flbas); + } else + in_use = ""; + + printf("mc : %#x\n", ns->mc); + if (human) + stdout_id_ns_mc(ns->mc); + printf("dpc : %#x\n", ns->dpc); + if (human) + stdout_id_ns_dpc(ns->dpc); + if (!cap_only) { + printf("dps : %#x\n", ns->dps); + if (human) + stdout_id_ns_dps(ns->dps); + printf("nmic : %#x\n", ns->nmic); + if (human) + stdout_id_ns_nmic(ns->nmic); + printf("rescap : %#x\n", ns->rescap); + if (human) + stdout_id_ns_rescap(ns->rescap); + printf("fpi : %#x\n", ns->fpi); + if (human) + stdout_id_ns_fpi(ns->fpi); + printf("dlfeat : %d\n", ns->dlfeat); + if (human) + stdout_id_ns_dlfeat(ns->dlfeat); + printf("nawun : %d\n", le16_to_cpu(ns->nawun)); + printf("nawupf : %d\n", le16_to_cpu(ns->nawupf)); + printf("nacwu : %d\n", le16_to_cpu(ns->nacwu)); + printf("nabsn : %d\n", le16_to_cpu(ns->nabsn)); + printf("nabo : %d\n", le16_to_cpu(ns->nabo)); + printf("nabspf : %d\n", le16_to_cpu(ns->nabspf)); + printf("noiob : %d\n", le16_to_cpu(ns->noiob)); + printf("nvmcap : %s\n", + uint128_t_to_l10n_string(le128_to_cpu(ns->nvmcap))); + if (ns->nsfeat & 0x10) { + printf("npwg : %u\n", le16_to_cpu(ns->npwg)); + printf("npwa : %u\n", le16_to_cpu(ns->npwa)); + printf("npdg : %u\n", le16_to_cpu(ns->npdg)); + printf("npda : %u\n", le16_to_cpu(ns->npda)); + printf("nows : %u\n", le16_to_cpu(ns->nows)); + } + printf("mssrl : %u\n", le16_to_cpu(ns->mssrl)); + printf("mcl : %u\n", le32_to_cpu(ns->mcl)); + printf("msrc : %u\n", ns->msrc); + } + printf("nulbaf : %u\n", ns->nulbaf); + if (!cap_only) { + printf("anagrpid: %u\n", le32_to_cpu(ns->anagrpid)); + printf("nsattr : %u\n", ns->nsattr); + printf("nvmsetid: %d\n", le16_to_cpu(ns->nvmsetid)); + printf("endgid : %d\n", le16_to_cpu(ns->endgid)); + + printf("nguid : "); + for (i = 0; i < 16; i++) + printf("%02x", ns->nguid[i]); + printf("\n"); + + printf("eui64 : "); + for (i = 0; i < 8; i++) + printf("%02x", ns->eui64[i]); + printf("\n"); + } + + nvme_id_ns_flbas_to_lbaf_inuse(ns->flbas, &flbas); + for (i = 0; i <= ns->nlbaf + ns->nulbaf; i++) { + if (human) + printf("LBA Format %2d : Metadata Size: %-3d bytes - " + "Data Size: %-2d bytes - Relative Performance: %#x %s %s\n", + i, le16_to_cpu(ns->lbaf[i].ms), + 1 << ns->lbaf[i].ds, ns->lbaf[i].rp, + ns->lbaf[i].rp == 3 ? "Degraded" : + ns->lbaf[i].rp == 2 ? "Good" : + ns->lbaf[i].rp == 1 ? "Better" : "Best", + i == flbas ? in_use : ""); + else + printf("lbaf %2d : ms:%-3d lbads:%-2d rp:%#x %s\n", i, + le16_to_cpu(ns->lbaf[i].ms), ns->lbaf[i].ds, + ns->lbaf[i].rp, i == flbas ? in_use : ""); + } + + if (vs && !cap_only) { + printf("vs[]:\n"); + d(ns->vs, sizeof(ns->vs), 16, 1); + } +} + +static void stdout_cmd_set_independent_id_ns_nsfeat(__u8 nsfeat) +{ + __u8 rsvd6 = (nsfeat & 0xE0) >> 6; + __u8 vwcnp = (nsfeat & 0x20) >> 5; + __u8 rmedia = (nsfeat & 0x10) >> 4; + __u8 uidreuse = (nsfeat & 0x8) >> 3; + __u8 rsvd0 = (nsfeat & 0x7); + if (rsvd6) + printf(" [7:6] : %#x\tReserved\n", rsvd6); + printf(" [5:5] : %#x\tVolatile Write Cache is %sPresent\n", + vwcnp, vwcnp ? "" : "Not "); + printf(" [4:4] : %#x\tNamespace %sstore data on rotational media\n", + rmedia, rmedia ? "" : "does not "); + printf(" [3:3] : %#x\tNGUID and EUI64 fields if non-zero, %sReused\n", + uidreuse, uidreuse ? "Never " : ""); + if (rsvd0) + printf(" [2:0] : %#x\tReserved\n", rsvd0); + printf("\n"); +} + +static void stdout_cmd_set_independent_id_ns_nstat(__u8 nstat) +{ + __u8 rsvd1 = (nstat & 0xfe) >> 1; + __u8 nrdy = nstat & 0x1; + if (rsvd1) + printf(" [7:1] : %#x\tReserved\n", rsvd1); + printf(" [0:0] : %#x\tName space is %sready\n", + nrdy, nrdy ? "" : "not "); + printf("\n"); +} + +static void stdout_cmd_set_independent_id_ns(struct nvme_id_independent_id_ns *ns, + unsigned int nsid) +{ + int human = stdout_print_ops.flags & VERBOSE; + + printf("NVME Identify Command Set Independent Namespace %d:\n", nsid); + printf("nsfeat : %#x\n", ns->nsfeat); + if (human) + stdout_cmd_set_independent_id_ns_nsfeat(ns->nsfeat); + printf("nmic : %#x\n", ns->nmic); + if (human) + stdout_id_ns_nmic(ns->nmic); + printf("rescap : %#x\n", ns->rescap); + if (human) + stdout_id_ns_rescap(ns->rescap); + printf("fpi : %#x\n", ns->fpi); + if (human) + stdout_id_ns_fpi(ns->fpi); + printf("anagrpid: %u\n", le32_to_cpu(ns->anagrpid)); + printf("nsattr : %u\n", ns->nsattr); + if (human) + stdout_id_ns_nsattr(ns->nsattr); + printf("nvmsetid: %d\n", le16_to_cpu(ns->nvmsetid)); + printf("endgid : %d\n", le16_to_cpu(ns->endgid)); + + printf("nstat : %#x\n", ns->nstat); + if (human) + stdout_cmd_set_independent_id_ns_nstat(ns->nstat); +} + +static void stdout_id_ns_descs(void *data, unsigned int nsid) +{ + int pos, len = 0; + int i; + __u8 uuid[NVME_UUID_LEN]; + char uuid_str[NVME_UUID_LEN_STRING]; + __u8 eui64[8]; + __u8 nguid[16]; + __u8 csi; + + printf("NVME Namespace Identification Descriptors NS %d:\n", nsid); + for (pos = 0; pos < NVME_IDENTIFY_DATA_SIZE; pos += len) { + struct nvme_ns_id_desc *cur = data + pos; + + if (cur->nidl == 0) + break; + + switch (cur->nidt) { + case NVME_NIDT_EUI64: + memcpy(eui64, data + pos + sizeof(*cur), sizeof(eui64)); + printf("eui64 : "); + for (i = 0; i < 8; i++) + printf("%02x", eui64[i]); + printf("\n"); + len = sizeof(eui64); + break; + case NVME_NIDT_NGUID: + memcpy(nguid, data + pos + sizeof(*cur), sizeof(nguid)); + printf("nguid : "); + for (i = 0; i < 16; i++) + printf("%02x", nguid[i]); + printf("\n"); + len = sizeof(nguid); + break; + case NVME_NIDT_UUID: + memcpy(uuid, data + pos + sizeof(*cur), 16); + nvme_uuid_to_string(uuid, uuid_str); + printf("uuid : %s\n", uuid_str); + len = sizeof(uuid); + break; + case NVME_NIDT_CSI: + memcpy(&csi, data + pos + sizeof(*cur), 1); + printf("csi : %#x\n", csi); + len += sizeof(csi); + break; + default: + /* Skip unknown types */ + len = cur->nidl; + break; + } + + len += sizeof(*cur); + } +} + +static void print_psd_workload(__u8 apw) +{ + switch (apw & 0x7) { + case NVME_PSD_WORKLOAD_NP: + /* Unknown or not provided */ + printf("-"); + break; + + case 1: + /* Extended idle period with burst of random write */ + printf("1MiB 32 RW, 30s idle"); + break; + + case 2: + /* Heavy sequential writes */ + printf("80K 128KiB SW"); + break; + + default: + printf("reserved"); + } +} + +static void print_ps_power_and_scale(__le16 ctr_power, __u8 scale) +{ + __u16 power = le16_to_cpu(ctr_power); + + switch (scale & 0x3) { + case NVME_PSD_PS_NOT_REPORTED: + /* Not reported for this power state */ + printf("-"); + break; + + case NVME_PSD_PS_100_MICRO_WATT: + /* Units of 0.0001W */ + printf("%01u.%04uW", power / 10000, power % 10000); + break; + + case NVME_PSD_PS_10_MILLI_WATT: + /* Units of 0.01W */ + printf("%01u.%02uW", power / 100, power % 100); + break; + + default: + printf("reserved"); + } +} + +static void stdout_id_ctrl_power(struct nvme_id_ctrl *ctrl) +{ + int i; + + for (i = 0; i <= ctrl->npss; i++) { + __u16 max_power = le16_to_cpu(ctrl->psd[i].mp); + + printf("ps %4d : mp:", i); + + if (ctrl->psd[i].flags & NVME_PSD_FLAGS_MXPS) + printf("%01u.%04uW ", max_power / 10000, max_power % 10000); + else + printf("%01u.%02uW ", max_power / 100, max_power % 100); + + if (ctrl->psd[i].flags & NVME_PSD_FLAGS_NOPS) + printf("non-"); + + printf("operational enlat:%d exlat:%d rrt:%d rrl:%d\n" + " rwt:%d rwl:%d idle_power:", + le32_to_cpu(ctrl->psd[i].enlat), + le32_to_cpu(ctrl->psd[i].exlat), + ctrl->psd[i].rrt, ctrl->psd[i].rrl, + ctrl->psd[i].rwt, ctrl->psd[i].rwl); + print_ps_power_and_scale(ctrl->psd[i].idlp, + nvme_psd_power_scale(ctrl->psd[i].ips)); + printf(" active_power:"); + print_ps_power_and_scale(ctrl->psd[i].actp, + nvme_psd_power_scale(ctrl->psd[i].apws)); + printf("\n active_power_workload:"); + print_psd_workload(ctrl->psd[i].apws); + printf("\n"); + + } +} + +static void stdout_id_ctrl(struct nvme_id_ctrl *ctrl, + void (*vendor_show)(__u8 *vs, struct json_object *root)) +{ + bool human = stdout_print_ops.flags & VERBOSE, vs = stdout_print_ops.flags & VS; + + printf("NVME Identify Controller:\n"); + printf("vid : %#x\n", le16_to_cpu(ctrl->vid)); + printf("ssvid : %#x\n", le16_to_cpu(ctrl->ssvid)); + printf("sn : %-.*s\n", (int)sizeof(ctrl->sn), ctrl->sn); + printf("mn : %-.*s\n", (int)sizeof(ctrl->mn), ctrl->mn); + printf("fr : %-.*s\n", (int)sizeof(ctrl->fr), ctrl->fr); + printf("rab : %d\n", ctrl->rab); + printf("ieee : %02x%02x%02x\n", + ctrl->ieee[2], ctrl->ieee[1], ctrl->ieee[0]); + printf("cmic : %#x\n", ctrl->cmic); + if (human) + stdout_id_ctrl_cmic(ctrl->cmic); + printf("mdts : %d\n", ctrl->mdts); + printf("cntlid : %#x\n", le16_to_cpu(ctrl->cntlid)); + printf("ver : %#x\n", le32_to_cpu(ctrl->ver)); + printf("rtd3r : %#x\n", le32_to_cpu(ctrl->rtd3r)); + printf("rtd3e : %#x\n", le32_to_cpu(ctrl->rtd3e)); + printf("oaes : %#x\n", le32_to_cpu(ctrl->oaes)); + if (human) + stdout_id_ctrl_oaes(ctrl->oaes); + printf("ctratt : %#x\n", le32_to_cpu(ctrl->ctratt)); + if (human) + stdout_id_ctrl_ctratt(ctrl->ctratt); + printf("rrls : %#x\n", le16_to_cpu(ctrl->rrls)); + printf("cntrltype : %d\n", ctrl->cntrltype); + if (human) + stdout_id_ctrl_cntrltype(ctrl->cntrltype); + printf("fguid : %s\n", util_uuid_to_string(ctrl->fguid)); + printf("crdt1 : %u\n", le16_to_cpu(ctrl->crdt1)); + printf("crdt2 : %u\n", le16_to_cpu(ctrl->crdt2)); + printf("crdt3 : %u\n", le16_to_cpu(ctrl->crdt3)); + printf("nvmsr : %u\n", ctrl->nvmsr); + if (human) + stdout_id_ctrl_nvmsr(ctrl->nvmsr); + printf("vwci : %u\n", ctrl->vwci); + if (human) + stdout_id_ctrl_vwci(ctrl->vwci); + printf("mec : %u\n", ctrl->mec); + if (human) + stdout_id_ctrl_mec(ctrl->mec); + + printf("oacs : %#x\n", le16_to_cpu(ctrl->oacs)); + if (human) + stdout_id_ctrl_oacs(ctrl->oacs); + printf("acl : %d\n", ctrl->acl); + printf("aerl : %d\n", ctrl->aerl); + printf("frmw : %#x\n", ctrl->frmw); + if (human) + stdout_id_ctrl_frmw(ctrl->frmw); + printf("lpa : %#x\n", ctrl->lpa); + if (human) + stdout_id_ctrl_lpa(ctrl->lpa); + printf("elpe : %d\n", ctrl->elpe); + if (human) + stdout_id_ctrl_elpe(ctrl->elpe); + printf("npss : %d\n", ctrl->npss); + if (human) + stdout_id_ctrl_npss(ctrl->npss); + printf("avscc : %#x\n", ctrl->avscc); + if (human) + stdout_id_ctrl_avscc(ctrl->avscc); + printf("apsta : %#x\n", ctrl->apsta); + if (human) + stdout_id_ctrl_apsta(ctrl->apsta); + printf("wctemp : %d\n", le16_to_cpu(ctrl->wctemp)); + if (human) + stdout_id_ctrl_wctemp(ctrl->wctemp); + printf("cctemp : %d\n", le16_to_cpu(ctrl->cctemp)); + if (human) + stdout_id_ctrl_cctemp(ctrl->cctemp); + printf("mtfa : %d\n", le16_to_cpu(ctrl->mtfa)); + printf("hmpre : %u\n", le32_to_cpu(ctrl->hmpre)); + printf("hmmin : %u\n", le32_to_cpu(ctrl->hmmin)); + printf("tnvmcap : %s\n", + uint128_t_to_l10n_string(le128_to_cpu(ctrl->tnvmcap))); + if (human) + stdout_id_ctrl_tnvmcap(ctrl->tnvmcap); + printf("unvmcap : %s\n", + uint128_t_to_l10n_string(le128_to_cpu(ctrl->unvmcap))); + if (human) + stdout_id_ctrl_unvmcap(ctrl->unvmcap); + printf("rpmbs : %#x\n", le32_to_cpu(ctrl->rpmbs)); + if (human) + stdout_id_ctrl_rpmbs(ctrl->rpmbs); + printf("edstt : %d\n", le16_to_cpu(ctrl->edstt)); + printf("dsto : %d\n", ctrl->dsto); + printf("fwug : %d\n", ctrl->fwug); + printf("kas : %d\n", le16_to_cpu(ctrl->kas)); + printf("hctma : %#x\n", le16_to_cpu(ctrl->hctma)); + if (human) + stdout_id_ctrl_hctma(ctrl->hctma); + printf("mntmt : %d\n", le16_to_cpu(ctrl->mntmt)); + if (human) + stdout_id_ctrl_mntmt(ctrl->mntmt); + printf("mxtmt : %d\n", le16_to_cpu(ctrl->mxtmt)); + if (human) + stdout_id_ctrl_mxtmt(ctrl->mxtmt); + printf("sanicap : %#x\n", le32_to_cpu(ctrl->sanicap)); + if (human) + stdout_id_ctrl_sanicap(ctrl->sanicap); + printf("hmminds : %u\n", le32_to_cpu(ctrl->hmminds)); + printf("hmmaxd : %d\n", le16_to_cpu(ctrl->hmmaxd)); + printf("nsetidmax : %d\n", le16_to_cpu(ctrl->nsetidmax)); + printf("endgidmax : %d\n", le16_to_cpu(ctrl->endgidmax)); + printf("anatt : %d\n", ctrl->anatt); + printf("anacap : %d\n", ctrl->anacap); + if (human) + stdout_id_ctrl_anacap(ctrl->anacap); + printf("anagrpmax : %u\n", ctrl->anagrpmax); + printf("nanagrpid : %u\n", le32_to_cpu(ctrl->nanagrpid)); + printf("pels : %u\n", le32_to_cpu(ctrl->pels)); + printf("domainid : %d\n", le16_to_cpu(ctrl->domainid)); + printf("megcap : %s\n", + uint128_t_to_l10n_string(le128_to_cpu(ctrl->megcap))); + printf("sqes : %#x\n", ctrl->sqes); + if (human) + stdout_id_ctrl_sqes(ctrl->sqes); + printf("cqes : %#x\n", ctrl->cqes); + if (human) + stdout_id_ctrl_cqes(ctrl->cqes); + printf("maxcmd : %d\n", le16_to_cpu(ctrl->maxcmd)); + printf("nn : %u\n", le32_to_cpu(ctrl->nn)); + printf("oncs : %#x\n", le16_to_cpu(ctrl->oncs)); + if (human) + stdout_id_ctrl_oncs(ctrl->oncs); + printf("fuses : %#x\n", le16_to_cpu(ctrl->fuses)); + if (human) + stdout_id_ctrl_fuses(ctrl->fuses); + printf("fna : %#x\n", ctrl->fna); + if (human) + stdout_id_ctrl_fna(ctrl->fna); + printf("vwc : %#x\n", ctrl->vwc); + if (human) + stdout_id_ctrl_vwc(ctrl->vwc); + printf("awun : %d\n", le16_to_cpu(ctrl->awun)); + printf("awupf : %d\n", le16_to_cpu(ctrl->awupf)); + printf("icsvscc : %d\n", ctrl->icsvscc); + if (human) + stdout_id_ctrl_icsvscc(ctrl->icsvscc); + printf("nwpc : %d\n", ctrl->nwpc); + if (human) + stdout_id_ctrl_nwpc(ctrl->nwpc); + printf("acwu : %d\n", le16_to_cpu(ctrl->acwu)); + printf("ocfs : %#x\n", le16_to_cpu(ctrl->ocfs)); + if (human) + stdout_id_ctrl_ocfs(ctrl->ocfs); + printf("sgls : %#x\n", le32_to_cpu(ctrl->sgls)); + if (human) + stdout_id_ctrl_sgls(ctrl->sgls); + printf("mnan : %u\n", le32_to_cpu(ctrl->mnan)); + printf("maxdna : %s\n", + uint128_t_to_l10n_string(le128_to_cpu(ctrl->maxdna))); + printf("maxcna : %u\n", le32_to_cpu(ctrl->maxcna)); + printf("subnqn : %-.*s\n", (int)sizeof(ctrl->subnqn), ctrl->subnqn); + printf("ioccsz : %u\n", le32_to_cpu(ctrl->ioccsz)); + printf("iorcsz : %u\n", le32_to_cpu(ctrl->iorcsz)); + printf("icdoff : %d\n", le16_to_cpu(ctrl->icdoff)); + printf("fcatt : %#x\n", ctrl->fcatt); + if (human) + stdout_id_ctrl_fcatt(ctrl->fcatt); + printf("msdbd : %d\n", ctrl->msdbd); + printf("ofcs : %d\n", le16_to_cpu(ctrl->ofcs)); + if (human) + stdout_id_ctrl_ofcs(ctrl->ofcs); + + stdout_id_ctrl_power(ctrl); + if (vendor_show) + vendor_show(ctrl->vs, NULL); + else if (vs) { + printf("vs[]:\n"); + d(ctrl->vs, sizeof(ctrl->vs), 16, 1); + } +} + +static void stdout_id_ctrl_nvm(struct nvme_id_ctrl_nvm *ctrl_nvm) +{ + printf("NVMe Identify Controller NVM:\n"); + printf("vsl : %u\n", ctrl_nvm->vsl); + printf("wzsl : %u\n", ctrl_nvm->wzsl); + printf("wusl : %u\n", ctrl_nvm->wusl); + printf("dmrl : %u\n", ctrl_nvm->dmrl); + printf("dmrsl : %u\n", le32_to_cpu(ctrl_nvm->dmrsl)); + printf("dmsl : %"PRIu64"\n", le64_to_cpu(ctrl_nvm->dmsl)); +} + +static void stdout_nvm_id_ns_pic(__u8 pic) +{ + __u8 rsvd = (pic & 0xF8) >> 3; + __u8 stcrs = (pic & 0x3) >> 2; + __u8 pic_16bpistm = (pic & 0x2) >> 1; + __u8 pic_16bpists = pic & 0x1; + + if (rsvd) + printf(" [7:3] : %#x\tReserved\n", rsvd); + printf(" [2:2] : %#x\tStorage Tag Check Read Support\n", stcrs); + printf(" [1:1] : %#x\t16b Guard Protection Information Storage Tag Mask\n", + pic_16bpistm); + printf(" [0:0] : %#x\t16b Guard Protection Information Storage Tag Support\n", + pic_16bpists); + printf("\n"); +} + +static void stdout_nvm_id_ns(struct nvme_nvm_id_ns *nvm_ns, unsigned int nsid, + struct nvme_id_ns *ns, unsigned int lba_index, + bool cap_only) +{ + int i, verbose = stdout_print_ops.flags & VERBOSE; + __u32 elbaf; + int pif, sts; + char *in_use = "(in use)"; + + if (!cap_only) { + printf("NVMe NVM Identify Namespace %d:\n", nsid); + printf("lbstm : %#"PRIx64"\n", le64_to_cpu(nvm_ns->lbstm)); + } else { + printf("NVMe NVM Identify Namespace for LBA format[%d]:\n", lba_index); + in_use = ""; + } + printf("pic : %#x\n", nvm_ns->pic); + if (verbose) + stdout_nvm_id_ns_pic(nvm_ns->pic); + + for (i = 0; i <= ns->nlbaf + ns->nulbaf; i++) { + elbaf = le32_to_cpu(nvm_ns->elbaf[i]); + pif = (elbaf >> 7) & 0x3; + sts = elbaf & 0x7f; + if (verbose) + printf("Extended LBA Format %2d : Protection Information Format: " + "%s(%d) - Storage Tag Size (MSB): %-2d %s\n", + i, pif == 3 ? "Reserved" : + pif == 2 ? "64b Guard" : + pif == 1 ? "32b Guard" : "16b Guard", + pif, sts, i == (ns->flbas & 0xf) ? in_use : ""); + else + printf("elbaf %2d : pif:%d lbads:%-2d %s\n", i, + pif, sts, i == (ns->flbas & 0xf) ? in_use : ""); + } +} + +static void stdout_zns_id_ctrl(struct nvme_zns_id_ctrl *ctrl) +{ + printf("NVMe ZNS Identify Controller:\n"); + printf("zasl : %u\n", ctrl->zasl); +} + +static void show_nvme_id_ns_zoned_zoc(__le16 ns_zoc) +{ + __u16 zoc = le16_to_cpu(ns_zoc); + __u8 rsvd = (zoc & 0xfffc) >> 2; + __u8 ze = (zoc & 0x2) >> 1; + __u8 vzc = zoc & 0x1; + if (rsvd) + printf(" [15:2] : %#x\tReserved\n", rsvd); + printf(" [1:1] : %#x\t Zone Active Excursions: %s\n", + ze, ze ? "Yes (Host support required)" : "No"); + printf(" [0:0] : %#x\t Variable Zone Capacity: %s\n", + vzc, vzc ? "Yes (Host support required)" : "No"); + printf("\n"); +} + +static void show_nvme_id_ns_zoned_ozcs(__le16 ns_ozcs) +{ + __u16 ozcs = le16_to_cpu(ns_ozcs); + __u8 rsvd = (ozcs & 0xfffc) >> 2; + __u8 razb = ozcs & 0x1; + __u8 zrwasup = (ozcs & 0x2) >> 1; + + if (rsvd) + printf(" [15:1] : %#x\tReserved\n", rsvd); + printf(" [0:0] : %#x\t Read Across Zone Boundaries: %s\n", + razb, razb ? "Yes" : "No"); + printf(" [1:1] : %#x\t Zone Random Write Area: %s\n", zrwasup, + zrwasup ? "Yes" : "No"); +} + +static void stdout_zns_id_ns_recommended_limit(__le32 ns_rl, int human, + const char *target_limit) +{ + unsigned int recommended_limit = le32_to_cpu(ns_rl); + if (!recommended_limit && human) + printf("%s : Not Reported\n", target_limit); + else + printf("%s : %u\n", target_limit, recommended_limit); +} + +static void stdout_zns_id_ns_zrwacap(__u8 zrwacap) +{ + __u8 rsvd = (zrwacap & 0xfe) >> 1; + __u8 expflushsup = zrwacap & 0x1; + + if (rsvd) + printf(" [7:1] : %#x\tReserved\n", rsvd); + printf(" [0:0] : %#x\t Explicit ZRWA Flush Operations: %s\n", + expflushsup, expflushsup ? "Yes" : "No"); +} + +static void stdout_zns_id_ns(struct nvme_zns_id_ns *ns, + struct nvme_id_ns *id_ns) +{ + int human = stdout_print_ops.flags & VERBOSE, vs = stdout_print_ops.flags & VS; + uint8_t lbaf; + int i; + + nvme_id_ns_flbas_to_lbaf_inuse(id_ns->flbas, &lbaf); + + printf("ZNS Command Set Identify Namespace:\n"); + + if (human) { + printf("zoc : %u\tZone Operation Characteristics\n", le16_to_cpu(ns->zoc)); + show_nvme_id_ns_zoned_zoc(ns->zoc); + } else { + printf("zoc : %u\n", le16_to_cpu(ns->zoc)); + } + + if (human) { + printf("ozcs : %u\tOptional Zoned Command Support\n", le16_to_cpu(ns->ozcs)); + show_nvme_id_ns_zoned_ozcs(ns->ozcs); + } else { + printf("ozcs : %u\n", le16_to_cpu(ns->ozcs)); + } + + if (human) { + if (ns->mar == 0xffffffff) { + printf("mar : No Active Resource Limit\n"); + } else { + printf("mar : %u\tActive Resources\n", le32_to_cpu(ns->mar) + 1); + } + } else { + printf("mar : %#x\n", le32_to_cpu(ns->mar)); + } + + if (human) { + if (ns->mor == 0xffffffff) { + printf("mor : No Open Resource Limit\n"); + } else { + printf("mor : %u\tOpen Resources\n", le32_to_cpu(ns->mor) + 1); + } + } else { + printf("mor : %#x\n", le32_to_cpu(ns->mor)); + } + + stdout_zns_id_ns_recommended_limit(ns->rrl, human, "rrl "); + stdout_zns_id_ns_recommended_limit(ns->frl, human, "frl "); + stdout_zns_id_ns_recommended_limit(ns->rrl1, human, "rrl1"); + stdout_zns_id_ns_recommended_limit(ns->rrl2, human, "rrl2"); + stdout_zns_id_ns_recommended_limit(ns->rrl3, human, "rrl3"); + stdout_zns_id_ns_recommended_limit(ns->frl, human, "frl1"); + stdout_zns_id_ns_recommended_limit(ns->frl, human, "frl2"); + stdout_zns_id_ns_recommended_limit(ns->frl, human, "frl3"); + + printf("numzrwa : %#x\n", le32_to_cpu(ns->numzrwa)); + printf("zrwafg : %u\n", le16_to_cpu(ns->zrwafg)); + printf("zrwasz : %u\n", le16_to_cpu(ns->zrwasz)); + if (human) { + printf("zrwacap : %u\tZone Random Write Area Capability\n", ns->zrwacap); + stdout_zns_id_ns_zrwacap(ns->zrwacap); + } else { + printf("zrwacap : %u\n", ns->zrwacap); + } + + for (i = 0; i <= id_ns->nlbaf; i++){ + if (human) + printf("LBA Format Extension %2d : Zone Size: 0x%"PRIx64" LBAs - " + "Zone Descriptor Extension Size: %-1d bytes%s\n", + i, le64_to_cpu(ns->lbafe[i].zsze), ns->lbafe[i].zdes << 6, + i == lbaf ? " (in use)" : ""); + else + printf("lbafe %2d: zsze:0x%"PRIx64" zdes:%u%s\n", i, + (uint64_t)le64_to_cpu(ns->lbafe[i].zsze), + ns->lbafe[i].zdes, i == lbaf ? " (in use)" : ""); + } + + if (vs) { + printf("vs[] :\n"); + d(ns->vs, sizeof(ns->vs), 16, 1); + } +} + +static void stdout_list_ns(struct nvme_ns_list *ns_list) +{ + int i; + + for (i = 0; i < 1024; i++) { + if (ns_list->ns[i]) + printf("[%4u]:%#x\n", i, le32_to_cpu(ns_list->ns[i])); + } +} + +static void stdout_zns_changed(struct nvme_zns_changed_zone_log *log) +{ + uint16_t nrzid; + int i; + + nrzid = le16_to_cpu(log->nrzid); + printf("NVMe Changed Zone List:\n"); + + if (nrzid == 0xFFFF) { + printf("Too many zones have changed to fit into the log. Use report zones for changes.\n"); + return; + } + + printf("nrzid: %u\n", nrzid); + for (i = 0; i < nrzid; i++) + printf("zid %03d: %"PRIu64"\n", i, (uint64_t)le64_to_cpu(log->zid[i])); +} + +static void stdout_zns_report_zone_attributes(__u8 za, __u8 zai) +{ + const char *const recommended_limit[4] = {"","1","2","3"}; + printf("Attrs: Zone Descriptor Extension is %sVaild\n", + (za & NVME_ZNS_ZA_ZDEV)? "" : "Not "); + if(za & NVME_ZNS_ZA_RZR) { + printf(" Reset Zone Recommended with Reset Recommended Limit%s\n", + recommended_limit[(zai&0xd)>>2]); + } + if (za & NVME_ZNS_ZA_FZR) { + printf(" Finish Zone Recommended with Finish Recommended Limit%s\n", + recommended_limit[zai&0x3]); + } + if (za & NVME_ZNS_ZA_ZFC) { + printf(" Zone Finished by Controller\n"); + } +} + +static void stdout_zns_report_zones(void *report, __u32 descs, + __u8 ext_size, __u32 report_size, + struct json_object *zone_list) +{ + struct nvme_zone_report *r = report; + struct nvme_zns_desc *desc; + int i, verbose = stdout_print_ops.flags & VERBOSE; + __u64 nr_zones = le64_to_cpu(r->nr_zones); + + if (nr_zones < descs) + descs = nr_zones; + + for (i = 0; i < descs; i++) { + desc = (struct nvme_zns_desc *) + (report + sizeof(*r) + i * (sizeof(*desc) + ext_size)); + if(verbose) { + printf("SLBA: %#-10"PRIx64" WP: %#-10"PRIx64" Cap: %#-10"PRIx64" State: %-12s Type: %-14s\n", + (uint64_t)le64_to_cpu(desc->zslba), (uint64_t)le64_to_cpu(desc->wp), + (uint64_t)le64_to_cpu(desc->zcap), nvme_zone_state_to_string(desc->zs >> 4), + nvme_zone_type_to_string(desc->zt)); + stdout_zns_report_zone_attributes(desc->za, desc->zai); + } + else { + printf("SLBA: %#-10"PRIx64" WP: %#-10"PRIx64" Cap: %#-10"PRIx64" State: %#-4x Type: %#-4x Attrs: %#-4x AttrsInfo: %#-4x\n", + (uint64_t)le64_to_cpu(desc->zslba), (uint64_t)le64_to_cpu(desc->wp), + (uint64_t)le64_to_cpu(desc->zcap), desc->zs, desc->zt, + desc->za, desc->zai); + } + + if (ext_size && (desc->za & NVME_ZNS_ZA_ZDEV)) { + printf("Extension Data: "); + d((unsigned char *)desc + sizeof(*desc), ext_size, 16, 1); + printf("..\n"); + } + } +} + +static void stdout_list_ctrl(struct nvme_ctrl_list *ctrl_list, + __u16 num) +{ + int i; + + printf("num of ctrls present: %u\n", num); + for (i = 0; i < min(num, 2047); i++) { + printf("[%4u]:%#x\n", i, le16_to_cpu(ctrl_list->identifier[i])); + } +} + +static void stdout_id_nvmset(struct nvme_id_nvmset_list *nvmset, + unsigned int nvmset_id) +{ + int i; + + printf("NVME Identify NVM Set List %d:\n", nvmset_id); + printf("nid : %d\n", nvmset->nid); + printf(".................\n"); + for (i = 0; i < nvmset->nid; i++) { + printf(" NVM Set Attribute Entry[%2d]\n", i); + printf(".................\n"); + printf("nvmset_id : %d\n", + le16_to_cpu(nvmset->ent[i].endgid)); + printf("endurance_group_id : %d\n", + le16_to_cpu(nvmset->ent[i].endgid)); + printf("random_4k_read_typical : %u\n", + le32_to_cpu(nvmset->ent[i].rr4kt)); + printf("optimal_write_size : %u\n", + le32_to_cpu(nvmset->ent[i].ows)); + printf("total_nvmset_cap : %s\n", + uint128_t_to_l10n_string( + le128_to_cpu(nvmset->ent[i].tnvmsetcap))); + printf("unalloc_nvmset_cap : %s\n", + uint128_t_to_l10n_string( + le128_to_cpu(nvmset->ent[i].unvmsetcap))); + printf(".................\n"); + } +} + +static void stdout_primary_ctrl_caps_crt(__u8 crt) +{ + __u8 rsvd = (crt & 0xFC) >> 2; + __u8 vi = (crt & 0x2) >> 1; + __u8 vq = crt & 0x1; + + if (rsvd) + printf(" [7:2] : %#x\tReserved\n", rsvd); + printf(" [1:1] %#x\tVI Resources are %ssupported\n", vi, vi ? "" : "not "); + printf(" [0:0] %#x\tVQ Resources are %ssupported\n", vq, vq ? "" : "not "); +} + +static void stdout_primary_ctrl_cap(const struct nvme_primary_ctrl_cap *caps) +{ + int human = stdout_print_ops.flags & VERBOSE; + + printf("NVME Identify Primary Controller Capabilities:\n"); + printf("cntlid : %#x\n", le16_to_cpu(caps->cntlid)); + printf("portid : %#x\n", le16_to_cpu(caps->portid)); + printf("crt : %#x\n", caps->crt); + if (human) + stdout_primary_ctrl_caps_crt(caps->crt); + printf("vqfrt : %u\n", le32_to_cpu(caps->vqfrt)); + printf("vqrfa : %u\n", le32_to_cpu(caps->vqrfa)); + printf("vqrfap : %d\n", le16_to_cpu(caps->vqrfap)); + printf("vqprt : %d\n", le16_to_cpu(caps->vqprt)); + printf("vqfrsm : %d\n", le16_to_cpu(caps->vqfrsm)); + printf("vqgran : %d\n", le16_to_cpu(caps->vqgran)); + printf("vifrt : %u\n", le32_to_cpu(caps->vifrt)); + printf("virfa : %u\n", le32_to_cpu(caps->virfa)); + printf("virfap : %d\n", le16_to_cpu(caps->virfap)); + printf("viprt : %d\n", le16_to_cpu(caps->viprt)); + printf("vifrsm : %d\n", le16_to_cpu(caps->vifrsm)); + printf("vigran : %d\n", le16_to_cpu(caps->vigran)); +} + +static void stdout_list_secondary_ctrl(const struct nvme_secondary_ctrl_list *sc_list, + __u32 count) +{ + const struct nvme_secondary_ctrl *sc_entry = + &sc_list->sc_entry[0]; + static const char * const state_desc[] = { "Offline", "Online" }; + + __u16 num = sc_list->num; + __u32 entries = min(num, count); + int i; + + printf("Identify Secondary Controller List:\n"); + printf(" NUMID : Number of Identifiers : %d\n", num); + + for (i = 0; i < entries; i++) { + printf(" SCEntry[%-3d]:\n", i); + printf("................\n"); + printf(" SCID : Secondary Controller Identifier : 0x%.04x\n", + le16_to_cpu(sc_entry[i].scid)); + printf(" PCID : Primary Controller Identifier : 0x%.04x\n", + le16_to_cpu(sc_entry[i].pcid)); + printf(" SCS : Secondary Controller State : 0x%.04x (%s)\n", + sc_entry[i].scs, + state_desc[sc_entry[i].scs & 0x1]); + printf(" VFN : Virtual Function Number : 0x%.04x\n", + le16_to_cpu(sc_entry[i].vfn)); + printf(" NVQ : Num VQ Flex Resources Assigned : 0x%.04x\n", + le16_to_cpu(sc_entry[i].nvq)); + printf(" NVI : Num VI Flex Resources Assigned : 0x%.04x\n", + le16_to_cpu(sc_entry[i].nvi)); + } +} + +static void stdout_id_ns_granularity_list(const struct nvme_id_ns_granularity_list *glist) +{ + int i; + + printf("Identify Namespace Granularity List:\n"); + printf(" ATTR : Namespace Granularity Attributes: 0x%x\n", + glist->attributes); + printf(" NUMD : Number of Descriptors : %d\n", + glist->num_descriptors); + + /* Number of Descriptors is a 0's based value */ + for (i = 0; i <= glist->num_descriptors; i++) { + printf("\n Entry[%2d] :\n", i); + printf("................\n"); + printf(" NSG : Namespace Size Granularity : 0x%"PRIx64"\n", + le64_to_cpu(glist->entry[i].nszegran)); + printf(" NCG : Namespace Capacity Granularity : 0x%"PRIx64"\n", + le64_to_cpu(glist->entry[i].ncapgran)); + } +} + +static void stdout_id_uuid_list(const struct nvme_id_uuid_list *uuid_list) +{ + int i, human = stdout_print_ops.flags & VERBOSE; + + /* The 0th entry is reserved */ + printf("NVME Identify UUID:\n"); + for (i = 0; i < NVME_ID_UUID_LIST_MAX; i++) { + __u8 uuid[NVME_UUID_LEN]; + char *association = ""; + uint8_t identifier_association = uuid_list->entry[i].header & 0x3; + /* The list is terminated by a zero UUID value */ + if (memcmp(uuid_list->entry[i].uuid, zero_uuid, NVME_UUID_LEN) == 0) + break; + memcpy(&uuid, uuid_list->entry[i].uuid, NVME_UUID_LEN); + if (human) { + switch (identifier_association) { + case 0x0: + association = "No association reported"; + break; + case 0x1: + association = "associated with PCI Vendor ID"; + break; + case 0x2: + association = "associated with PCI Subsystem Vendor ID"; + break; + default: + association = "Reserved"; + break; + } + } + printf(" Entry[%3d]\n", i+1); + printf(".................\n"); + printf("association : 0x%x %s\n", identifier_association, association); + printf("UUID : %s", util_uuid_to_string(uuid)); + if (memcmp(uuid_list->entry[i].uuid, invalid_uuid, + sizeof(zero_uuid)) == 0) + printf(" (Invalid UUID)"); + printf("\n.................\n"); + } +} + +static void stdout_id_domain_list(struct nvme_id_domain_list *id_dom) +{ + int i; + + printf("Number of Domain Entries: %u\n", id_dom->num); + for (i = 0; i < id_dom->num; i++) { + printf("Domain Id for Attr Entry[%u]: %u\n", i, + le16_to_cpu(id_dom->domain_attr[i].dom_id)); + printf("Domain Capacity for Attr Entry[%u]: %s\n", i, + uint128_t_to_l10n_string( + le128_to_cpu(id_dom->domain_attr[i].dom_cap))); + printf("Unallocated Domain Capacity for Attr Entry[%u]: %s\n", i, + uint128_t_to_l10n_string( + le128_to_cpu(id_dom->domain_attr[i].unalloc_dom_cap))); + printf("Max Endurance Group Domain Capacity for Attr Entry[%u]: %s\n", i, + uint128_t_to_l10n_string( + le128_to_cpu(id_dom->domain_attr[i].max_egrp_dom_cap))); + } +} + +static void stdout_endurance_group_list(struct nvme_id_endurance_group_list *endgrp_list) +{ + int i; + __u16 num = le16_to_cpu(endgrp_list->num); + + printf("num of endurance group ids: %u\n", num); + for (i = 0; i < min(num, 2047); i++) { + printf("[%4u]:%#x\n", i, le16_to_cpu(endgrp_list->identifier[i])); + } +} + +static void stdout_id_iocs(struct nvme_id_iocs *iocs) +{ + __u16 i; + + for (i = 0; i < 512; i++) + if (iocs->iocsc[i]) + printf("I/O Command Set Combination[%u]:%"PRIx64"\n", i, + (uint64_t)le64_to_cpu(iocs->iocsc[i])); +} + +static void stdout_error_log(struct nvme_error_log_page *err_log, int entries, + const char *devname) +{ + int i; + + printf("Error Log Entries for device:%s entries:%d\n", devname, + entries); + printf(".................\n"); + for (i = 0; i < entries; i++) { + __u16 status = le16_to_cpu(err_log[i].status_field) >> 0x1; + + printf(" Entry[%2d] \n", i); + printf(".................\n"); + printf("error_count : %"PRIu64"\n", + le64_to_cpu(err_log[i].error_count)); + printf("sqid : %d\n", err_log[i].sqid); + printf("cmdid : %#x\n", err_log[i].cmdid); + printf("status_field : %#x(%s)\n", status, + nvme_status_to_string(status, false)); + printf("phase_tag : %#x\n", + le16_to_cpu(err_log[i].status_field & 0x1)); + printf("parm_err_loc : %#x\n", + err_log[i].parm_error_location); + printf("lba : %#"PRIx64"\n", + le64_to_cpu(err_log[i].lba)); + printf("nsid : %#x\n", err_log[i].nsid); + printf("vs : %d\n", err_log[i].vs); + printf("trtype : %s\n", + nvme_trtype_to_string(err_log[i].trtype)); + printf("csi : %d\n", err_log[i].csi); + printf("opcode : %#x\n", err_log[i].opcode); + printf("cs : %#"PRIx64"\n", + le64_to_cpu(err_log[i].cs)); + printf("trtype_spec_info: %#x\n", err_log[i].trtype_spec_info); + printf("log_page_version: %d\n", err_log[i].log_page_version); + printf(".................\n"); + } +} + +static void stdout_resv_report(struct nvme_resv_status *status, int bytes, + bool eds) +{ + int i, j, regctl, entries; + + regctl = status->regctl[0] | (status->regctl[1] << 8); + + printf("\nNVME Reservation status:\n\n"); + printf("gen : %u\n", le32_to_cpu(status->gen)); + printf("rtype : %d\n", status->rtype); + printf("regctl : %d\n", regctl); + printf("ptpls : %d\n", status->ptpls); + + /* check Extended Data Structure bit */ + if (!eds) { + /* + * if status buffer was too small, don't loop past the end of + * the buffer + */ + entries = (bytes - 24) / 24; + if (entries < regctl) + regctl = entries; + + for (i = 0; i < regctl; i++) { + printf("regctl[%d] :\n", i); + printf(" cntlid : %x\n", + le16_to_cpu(status->regctl_ds[i].cntlid)); + printf(" rcsts : %x\n", + status->regctl_ds[i].rcsts); + printf(" hostid : %"PRIx64"\n", + le64_to_cpu(status->regctl_ds[i].hostid)); + printf(" rkey : %"PRIx64"\n", + le64_to_cpu(status->regctl_ds[i].rkey)); + } + } else { + /* if status buffer was too small, don't loop past the end of the buffer */ + entries = (bytes - 64) / 64; + if (entries < regctl) + regctl = entries; + + for (i = 0; i < regctl; i++) { + printf("regctlext[%d] :\n", i); + printf(" cntlid : %x\n", + le16_to_cpu(status->regctl_eds[i].cntlid)); + printf(" rcsts : %x\n", + status->regctl_eds[i].rcsts); + printf(" rkey : %"PRIx64"\n", + le64_to_cpu(status->regctl_eds[i].rkey)); + printf(" hostid : "); + for (j = 0; j < 16; j++) + printf("%02x", + status->regctl_eds[i].hostid[j]); + printf("\n"); + } + } + printf("\n"); +} + +static void stdout_fw_log(struct nvme_firmware_slot *fw_log, + const char *devname) +{ + int i; + __le64 *frs; + + printf("Firmware Log for device:%s\n", devname); + printf("afi : %#x\n", fw_log->afi); + for (i = 0; i < 7; i++) { + if (fw_log->frs[i][0]) { + frs = (__le64 *)&fw_log->frs[i]; + printf("frs%d : %#016"PRIx64" (%s)\n", i + 1, + le64_to_cpu(*frs), + util_fw_to_string(fw_log->frs[i])); + } + } +} + +static void stdout_changed_ns_list_log(struct nvme_ns_list *log, + const char *devname) +{ + __u32 nsid; + int i; + + if (log->ns[0] != cpu_to_le32(NVME_NSID_ALL)) { + for (i = 0; i < NVME_ID_NS_LIST_MAX; i++) { + nsid = le32_to_cpu(log->ns[i]); + if (nsid == 0) + break; + + printf("[%4u]:%#x\n", i, nsid); + } + } else + printf("more than %d ns changed\n", + NVME_ID_NS_LIST_MAX); +} + +static void stdout_effects_log_human(FILE *stream, __u32 effect) +{ + const char *set = "+"; + const char *clr = "-"; + + fprintf(stream, " CSUPP+"); + fprintf(stream, " LBCC%s", (effect & NVME_CMD_EFFECTS_LBCC) ? set : clr); + fprintf(stream, " NCC%s", (effect & NVME_CMD_EFFECTS_NCC) ? set : clr); + fprintf(stream, " NIC%s", (effect & NVME_CMD_EFFECTS_NIC) ? set : clr); + fprintf(stream, " CCC%s", (effect & NVME_CMD_EFFECTS_CCC) ? set : clr); + fprintf(stream, " USS%s", (effect & NVME_CMD_EFFECTS_UUID_SEL) ? set : clr); + + if ((effect & NVME_CMD_EFFECTS_CSE_MASK) >> 16 == 0) + fprintf(stream, " No command restriction\n"); + else if ((effect & NVME_CMD_EFFECTS_CSE_MASK) >> 16 == 1) + fprintf(stream, " No other command for same namespace\n"); + else if ((effect & NVME_CMD_EFFECTS_CSE_MASK) >> 16 == 2) + fprintf(stream, " No other command for any namespace\n"); + else + fprintf(stream, " Reserved CSE\n"); +} + +static void stdout_effects_entry(FILE* stream, int admin, int index, + __le32 entry, unsigned int human) +{ + __u32 effect; + char *format_string; + + format_string = admin ? "ACS%-6d[%-32s] %08x" : "IOCS%-5d[%-32s] %08x"; + + effect = le32_to_cpu(entry); + if (effect & NVME_CMD_EFFECTS_CSUPP) { + fprintf(stream, format_string, index, nvme_cmd_to_string(admin, index), + effect); + if (human) + stdout_effects_log_human(stream, effect); + else + fprintf(stream, "\n"); + } +} + +static void stdout_effects_log_segment(int admin, int a, int b, + struct nvme_cmd_effects_log *effects, + char* header, int human) +{ + FILE *stream; + char *stream_location; + size_t stream_size; + + stream = open_memstream(&stream_location, &stream_size); + if (!stream) { + perror("Failed to open stream"); + return; + } + + for (int i = a; i < b; i++) { + if (admin) { + stdout_effects_entry(stream, admin, i, effects->acs[i], human); + } + else { + stdout_effects_entry(stream, admin, i, + effects->iocs[i], human); + } + } + + fclose(stream); + + if (stream_size && header) { + printf("%s\n", header); + fwrite(stream_location, stream_size, 1, stdout); + printf("\n"); + } + + free(stream_location); +} + +static void stdout_effects_log_page(enum nvme_csi csi, + struct nvme_cmd_effects_log *effects) +{ + int human = stdout_print_ops.flags & VERBOSE; + + switch (csi) { + case NVME_CSI_NVM: + printf("NVM Command Set Log Page\n"); + printf("%-.80s\n", dash); + break; + case NVME_CSI_ZNS: + printf("ZNS Command Set Log Page\n"); + printf("%-.80s\n", dash); + break; + default: + printf("Unknown Command Set Log Page\n"); + printf("%-.80s\n", dash); + break; + } + + stdout_effects_log_segment(1, 0, 0xbf, effects, "Admin Commands", human); + stdout_effects_log_segment(1, 0xc0, 0xff, effects, "Vendor Specific Admin Commands", human); + stdout_effects_log_segment(0, 0, 0x80, effects, "I/O Commands", human); + stdout_effects_log_segment(0, 0x80, 0x100, effects, "Vendor Specific I/O Commands", human); +} + +static void stdout_effects_log_pages(struct list_head *list) +{ + nvme_effects_log_node_t *node; + + list_for_each(list, node, node) { + stdout_effects_log_page(node->csi, &node->effects); + } +} + +static void stdout_support_log_human(__u32 support, __u8 lid) +{ + const char *set = "supported"; + const char *clr = "not supported"; + + printf(" LSUPP is %s\n", (support & 0x1) ? set : clr); + printf(" IOS is %s\n", ((support >> 0x1) & 0x1) ? set : clr); + if (lid == NVME_LOG_LID_PERSISTENT_EVENT) { + printf(" Establish Context and Read 512 Bytes of Header is %s\n", + ((support >> 0x16) & 0x1) ? set : clr); + } +} + +static void stdout_supported_log(struct nvme_supported_log_pages *support_log, + const char *devname) +{ + int lid, human = stdout_print_ops.flags& VERBOSE; + __u32 support = 0; + + printf("Support Log Pages Details for %s:\n", devname); + for (lid = 0; lid < 256; lid++) { + support = le32_to_cpu(support_log->lid_support[lid]); + if (support & 0x1) { + printf("LID 0x%x - %s\n", lid, nvme_log_to_string(lid)); + if (human) + stdout_support_log_human(support, lid); + } + } +} + +static void stdout_endurance_log(struct nvme_endurance_group_log *endurance_log, + __u16 group_id, const char *devname) +{ + printf("Endurance Group Log for NVME device:%s Group ID:%x\n", devname, + group_id); + printf("critical warning : %u\n", + endurance_log->critical_warning); + printf("avl_spare : %u\n", endurance_log->avl_spare); + printf("avl_spare_threshold : %u\n", + endurance_log->avl_spare_threshold); + printf("percent_used : %u%%\n", endurance_log->percent_used); + printf("endurance_estimate : %s\n", + uint128_t_to_l10n_string( + le128_to_cpu(endurance_log->endurance_estimate))); + printf("data_units_read : %s\n", + uint128_t_to_l10n_string( + le128_to_cpu(endurance_log->data_units_read))); + printf("data_units_written : %s\n", + uint128_t_to_l10n_string( + le128_to_cpu(endurance_log->data_units_written))); + printf("media_units_written : %s\n", + uint128_t_to_l10n_string( + le128_to_cpu(endurance_log->media_units_written))); + printf("host_read_cmds : %s\n", + uint128_t_to_l10n_string( + le128_to_cpu(endurance_log->host_read_cmds))); + printf("host_write_cmds : %s\n", + uint128_t_to_l10n_string( + le128_to_cpu(endurance_log->host_write_cmds))); + printf("media_data_integrity_err: %s\n", + uint128_t_to_l10n_string( + le128_to_cpu(endurance_log->media_data_integrity_err))); + printf("num_err_info_log_entries: %s\n", + uint128_t_to_l10n_string( + le128_to_cpu(endurance_log->num_err_info_log_entries))); +} + +static void stdout_smart_log(struct nvme_smart_log *smart, unsigned int nsid, + const char *devname) +{ + __u16 temperature = smart->temperature[1] << 8 | smart->temperature[0]; + int i; + bool human = stdout_print_ops.flags & VERBOSE; + + printf("Smart Log for NVME device:%s namespace-id:%x\n", devname, nsid); + printf("critical_warning : %#x\n", + smart->critical_warning); + + if (human) { + printf(" Available Spare[0] : %d\n", smart->critical_warning & 0x01); + printf(" Temp. Threshold[1] : %d\n", (smart->critical_warning & 0x02) >> 1); + printf(" NVM subsystem Reliability[2] : %d\n", (smart->critical_warning & 0x04) >> 2); + printf(" Read-only[3] : %d\n", (smart->critical_warning & 0x08) >> 3); + printf(" Volatile mem. backup failed[4] : %d\n", (smart->critical_warning & 0x10) >> 4); + printf(" Persistent Mem. RO[5] : %d\n", (smart->critical_warning & 0x20) >> 5); + } + + printf("temperature : %ld °C (%u K)\n", + kelvin_to_celsius(temperature), temperature); + printf("available_spare : %u%%\n", + smart->avail_spare); + printf("available_spare_threshold : %u%%\n", + smart->spare_thresh); + printf("percentage_used : %u%%\n", + smart->percent_used); + printf("endurance group critical warning summary: %#x\n", + smart->endu_grp_crit_warn_sumry); + printf("Data Units Read : %s (%s)\n", + uint128_t_to_l10n_string(le128_to_cpu(smart->data_units_read)), + uint128_t_to_si_string(le128_to_cpu(smart->data_units_read), + 1000 * 512)); + printf("Data Units Written : %s (%s)\n", + uint128_t_to_l10n_string(le128_to_cpu(smart->data_units_written)), + uint128_t_to_si_string(le128_to_cpu(smart->data_units_written), + 1000 * 512)); + printf("host_read_commands : %s\n", + uint128_t_to_l10n_string(le128_to_cpu(smart->host_reads))); + printf("host_write_commands : %s\n", + uint128_t_to_l10n_string(le128_to_cpu(smart->host_writes))); + printf("controller_busy_time : %s\n", + uint128_t_to_l10n_string(le128_to_cpu(smart->ctrl_busy_time))); + printf("power_cycles : %s\n", + uint128_t_to_l10n_string(le128_to_cpu(smart->power_cycles))); + printf("power_on_hours : %s\n", + uint128_t_to_l10n_string(le128_to_cpu(smart->power_on_hours))); + printf("unsafe_shutdowns : %s\n", + uint128_t_to_l10n_string(le128_to_cpu(smart->unsafe_shutdowns))); + printf("media_errors : %s\n", + uint128_t_to_l10n_string(le128_to_cpu(smart->media_errors))); + printf("num_err_log_entries : %s\n", + uint128_t_to_l10n_string(le128_to_cpu(smart->num_err_log_entries))); + printf("Warning Temperature Time : %u\n", + le32_to_cpu(smart->warning_temp_time)); + printf("Critical Composite Temperature Time : %u\n", + le32_to_cpu(smart->critical_comp_time)); + for (i = 0; i < 8; i++) { + __s32 temp = le16_to_cpu(smart->temp_sensor[i]); + + if (temp == 0) + continue; + printf("Temperature Sensor %d : %ld °C (%u K)\n", + i + 1, kelvin_to_celsius(temp), temp); + } + printf("Thermal Management T1 Trans Count : %u\n", + le32_to_cpu(smart->thm_temp1_trans_count)); + printf("Thermal Management T2 Trans Count : %u\n", + le32_to_cpu(smart->thm_temp2_trans_count)); + printf("Thermal Management T1 Total Time : %u\n", + le32_to_cpu(smart->thm_temp1_total_time)); + printf("Thermal Management T2 Total Time : %u\n", + le32_to_cpu(smart->thm_temp2_total_time)); +} + +static void stdout_ana_log(struct nvme_ana_log *ana_log, const char *devname, + size_t len) +{ + int offset = sizeof(struct nvme_ana_log); + struct nvme_ana_log *hdr = ana_log; + struct nvme_ana_group_desc *desc; + size_t nsid_buf_size; + void *base = ana_log; + __u32 nr_nsids; + int i, j; + + printf("Asymmetric Namespace Access Log for NVMe device: %s\n", + devname); + printf("ANA LOG HEADER :-\n"); + printf("chgcnt : %"PRIu64"\n", + le64_to_cpu(hdr->chgcnt)); + printf("ngrps : %u\n", le16_to_cpu(hdr->ngrps)); + printf("ANA Log Desc :-\n"); + + for (i = 0; i < le16_to_cpu(ana_log->ngrps); i++) { + desc = base + offset; + nr_nsids = le32_to_cpu(desc->nnsids); + nsid_buf_size = nr_nsids * sizeof(__le32); + + offset += sizeof(*desc); + printf("grpid : %u\n", le32_to_cpu(desc->grpid)); + printf("nnsids : %u\n", le32_to_cpu(desc->nnsids)); + printf("chgcnt : %"PRIu64"\n", + le64_to_cpu(desc->chgcnt)); + printf("state : %s\n", + nvme_ana_state_to_string(desc->state)); + for (j = 0; j < le32_to_cpu(desc->nnsids); j++) + printf(" nsid : %u\n", + le32_to_cpu(desc->nsids[j])); + printf("\n"); + offset += nsid_buf_size; + } +} + +static void stdout_self_test_result(struct nvme_st_result *res) +{ + static const char *const test_res[] = { + "Operation completed without error", + "Operation was aborted by a Device Self-test command", + "Operation was aborted by a Controller Level Reset", + "Operation was aborted due to a removal of a namespace from the namespace inventory", + "Operation was aborted due to the processing of a Format NVM command", + "A fatal error or unknown test error occurred while the controller was executing the"\ + " device self-test operation and the operation did not complete", + "Operation completed with a segment that failed and the segment that failed is not known", + "Operation completed with one or more failed segments and the first segment that failed "\ + "is indicated in the SegmentNumber field", + "Operation was aborted for unknown reason", + "Operation was aborted due to a sanitize operation", + "Reserved", + [NVME_ST_RESULT_NOT_USED] = "Entry not used (does not contain a result)", + }; + __u8 op, code; + + op = res->dsts & NVME_ST_RESULT_MASK; + printf(" Operation Result : %#x", op); + if (stdout_print_ops.flags & VERBOSE) + printf(" %s", (op < ARRAY_SIZE(test_res) && test_res[op]) ? + test_res[op] : test_res[ARRAY_SIZE(test_res) - 1]); + printf("\n"); + if (op == NVME_ST_RESULT_NOT_USED) + return; + + code = res->dsts >> NVME_ST_CODE_SHIFT; + printf(" Self Test Code : %x", code); + + if (stdout_print_ops.flags & VERBOSE) { + switch (code) { + case NVME_ST_CODE_SHORT: + printf(" Short device self-test operation"); + break; + case NVME_ST_CODE_EXTENDED: + printf(" Extended device self-test operation"); + break; + case NVME_ST_CODE_VS: + printf(" Vendor specific"); + break; + default: + printf(" Reserved"); + break; + } + } + printf("\n"); + + if (op == NVME_ST_RESULT_KNOWN_SEG_FAIL) + printf(" Segment Number : %#x\n", res->seg); + + printf(" Valid Diagnostic Information : %#x\n", res->vdi); + printf(" Power on hours (POH) : %#"PRIx64"\n", + (uint64_t)le64_to_cpu(res->poh)); + + if (res->vdi & NVME_ST_VALID_DIAG_INFO_NSID) + printf(" Namespace Identifier : %#x\n", + le32_to_cpu(res->nsid)); + if (res->vdi & NVME_ST_VALID_DIAG_INFO_FLBA) + printf(" Failing LBA : %#"PRIx64"\n", + (uint64_t)le64_to_cpu(res->flba)); + if (res->vdi & NVME_ST_VALID_DIAG_INFO_SCT) + printf(" Status Code Type : %#x\n", res->sct); + if (res->vdi & NVME_ST_VALID_DIAG_INFO_SC) { + printf(" Status Code : %#x", res->sc); + if (stdout_print_ops.flags & VERBOSE) + printf(" %s", nvme_status_to_string( + (res->sct & 7) << 8 | res->sc, false)); + printf("\n"); + } + printf(" Vendor Specific : %#x %#x\n", + res->vs[0], res->vs[1]); +} + +static void stdout_self_test_log(struct nvme_self_test_log *self_test, + __u8 dst_entries, __u32 size, + const char *devname) +{ + int i; + __u8 num_entries; + + printf("Device Self Test Log for NVME device:%s\n", devname); + printf("Current operation : %#x\n", self_test->current_operation); + printf("Current Completion : %u%%\n", self_test->completion); + num_entries = min(dst_entries, NVME_LOG_ST_MAX_RESULTS); + for (i = 0; i < num_entries; i++) { + printf("Self Test Result[%d]:\n", i); + stdout_self_test_result(&self_test->result[i]); + } +} + +static void stdout_sanitize_log_sprog(__u32 sprog) +{ + double percent; + + percent = (((double)sprog * 100) / 0x10000); + printf("\t(%f%%)\n", percent); +} + +static void stdout_sanitize_log_sstat(__u16 status) +{ + const char *str = nvme_sstat_status_to_string(status); + + printf("\t[2:0]\t%s\n", str); + str = "Number of completed passes if most recent operation was overwrite"; + printf("\t[7:3]\t%s:\t%u\n", str, + (status >> NVME_SANITIZE_SSTAT_COMPLETED_PASSES_SHIFT) & + NVME_SANITIZE_SSTAT_COMPLETED_PASSES_MASK); + + printf("\t [8]\t"); + if (status & NVME_SANITIZE_SSTAT_GLOBAL_DATA_ERASED) + str = "Global Data Erased set: no NS LB in the NVM subsystem "\ + "has been written to and no PMR in the NVM subsystem "\ + "has been enabled"; + else + str = "Global Data Erased cleared: a NS LB in the NVM "\ + "subsystem has been written to or a PMR in the NVM "\ + "subsystem has been enabled"; + printf("%s\n", str); +} + +static void stdout_estimate_sanitize_time(const char *text, uint32_t value) +{ + printf("%s: %u%s\n", text, value, + value == 0xffffffff ? " (No time period reported)" : ""); +} + +static void stdout_sanitize_log(struct nvme_sanitize_log_page *sanitize, + const char *devname) +{ + int human = stdout_print_ops.flags & VERBOSE; + __u16 status = le16_to_cpu(sanitize->sstat) & NVME_SANITIZE_SSTAT_STATUS_MASK; + + printf("Sanitize Progress (SPROG) : %u", + le16_to_cpu(sanitize->sprog)); + + if (human && status == NVME_SANITIZE_SSTAT_STATUS_IN_PROGESS) + stdout_sanitize_log_sprog(le16_to_cpu(sanitize->sprog)); + else + printf("\n"); + + printf("Sanitize Status (SSTAT) : %#x\n", + le16_to_cpu(sanitize->sstat)); + if (human) + stdout_sanitize_log_sstat(le16_to_cpu(sanitize->sstat)); + + printf("Sanitize Command Dword 10 Information (SCDW10) : %#x\n", + le32_to_cpu(sanitize->scdw10)); + stdout_estimate_sanitize_time("Estimated Time For Overwrite ", + le32_to_cpu(sanitize->eto)); + stdout_estimate_sanitize_time("Estimated Time For Block Erase ", + le32_to_cpu(sanitize->etbe)); + stdout_estimate_sanitize_time("Estimated Time For Crypto Erase ", + le32_to_cpu(sanitize->etce)); + stdout_estimate_sanitize_time("Estimated Time For Overwrite (No-Deallocate) ", + le32_to_cpu(sanitize->etond)); + stdout_estimate_sanitize_time("Estimated Time For Block Erase (No-Deallocate) ", + le32_to_cpu(sanitize->etbend)); + stdout_estimate_sanitize_time("Estimated Time For Crypto Erase (No-Deallocate)", + le32_to_cpu(sanitize->etcend)); +} + +static void stdout_select_result(__u32 result) +{ + if (result & 0x1) + printf(" Feature is saveable\n"); + if (result & 0x2) + printf(" Feature is per-namespace\n"); + if (result & 0x4) + printf(" Feature is changeable\n"); +} + +static void stdout_lba_range(struct nvme_lba_range_type *lbrt, int nr_ranges) +{ + int i, j; + + for (i = 0; i <= nr_ranges; i++) { + printf("\ttype : %#x - %s\n", lbrt->entry[i].type, + nvme_feature_lba_type_to_string(lbrt->entry[i].type)); + printf("\tattributes : %#x - %s, %s\n", lbrt->entry[i].attributes, + (lbrt->entry[i].attributes & 0x0001) ? + "LBA range may be overwritten" : + "LBA range should not be overwritten", + ((lbrt->entry[i].attributes & 0x0002) >> 1) ? + "LBA range should be hidden from the OS/EFI/BIOS" : + "LBA range should be visible from the OS/EFI/BIOS"); + printf("\tslba : %#"PRIx64"\n", le64_to_cpu(lbrt->entry[i].slba)); + printf("\tnlb : %#"PRIx64"\n", le64_to_cpu(lbrt->entry[i].nlb)); + printf("\tguid : "); + for (j = 0; j < 16; j++) + printf("%02x", lbrt->entry[i].guid[j]); + printf("\n"); + } +} + +static void stdout_auto_pst(struct nvme_feat_auto_pst *apst) +{ + int i; + __u64 value; + + printf( "\tAuto PST Entries"); + printf("\t.................\n"); + for (i = 0; i < 32; i++) { + value = le64_to_cpu(apst->apst_entry[i]); + + printf("\tEntry[%2d] \n", i); + printf("\t.................\n"); + printf("\tIdle Time Prior to Transition (ITPT): %u ms\n", + (__u32)(value >> NVME_APST_ENTRY_ITPT_SHIFT) & NVME_APST_ENTRY_ITPT_MASK); + printf("\tIdle Transition Power State (ITPS): %u\n", + (__u32)(value >> NVME_APST_ENTRY_ITPS_SHIFT ) & NVME_APST_ENTRY_ITPS_MASK); + printf("\t.................\n"); + } +} + +static void stdout_timestamp(struct nvme_timestamp *ts) +{ + struct tm *tm; + char buffer[320]; + time_t timestamp = int48_to_long(ts->timestamp) / 1000; + + tm = localtime(×tamp); + + printf("\tThe timestamp is : %'"PRIu64" (%s)\n", + int48_to_long(ts->timestamp), + strftime(buffer, sizeof(buffer), "%c %Z", tm) ? buffer : "-"); + printf("\t%s\n", (ts->attr & 2) ? + "The Timestamp field was initialized with a "\ + "Timestamp value using a Set Features command." : + "The Timestamp field was initialized "\ + "to ‘0’ by a Controller Level Reset."); + printf("\t%s\n", (ts->attr & 1) ? + "The controller may have stopped counting during vendor specific "\ + "intervals after the Timestamp value was initialized" : + "The controller counted time in milliseconds "\ + "continuously since the Timestamp value was initialized."); +} + +static void stdout_host_mem_buffer(struct nvme_host_mem_buf_attrs *hmb) +{ + printf("\tHost Memory Descriptor List Entry Count (HMDLEC): %u\n", + le32_to_cpu(hmb->hmdlec)); + printf("\tHost Memory Descriptor List Address (HMDLAU): 0x%x\n", + le32_to_cpu(hmb->hmdlau)); + printf("\tHost Memory Descriptor List Address (HMDLAL): 0x%x\n", + le32_to_cpu(hmb->hmdlal)); + printf("\tHost Memory Buffer Size (HSIZE): %u\n", + le32_to_cpu(hmb->hsize)); +} + +static void stdout_directive_show_fields(__u8 dtype, __u8 doper, + unsigned int result, unsigned char *buf) +{ + __u8 *field = buf; + int count, i; + + switch (dtype) { + case NVME_DIRECTIVE_DTYPE_IDENTIFY: + switch (doper) { + case NVME_DIRECTIVE_RECEIVE_IDENTIFY_DOPER_PARAM: + printf("\tDirective support \n"); + printf("\t\tIdentify Directive : %s\n", + (*field & 0x1) ? "supported":"not supported"); + printf("\t\tStream Directive : %s\n", + (*field & 0x2) ? "supported":"not supported"); + printf("\t\tData Placement Directive : %s\n", + (*field & 0x4) ? "supported":"not supported"); + printf("\tDirective enabled \n"); + printf("\t\tIdentify Directive : %s\n", + (*(field + 32) & 0x1) ? "enabled" : "disabled"); + printf("\t\tStream Directive : %s\n", + (*(field + 32) & 0x2) ? "enabled" : "disabled"); + printf("\t\tData Placement Directive : %s\n", + (*(field + 32) & 0x4) ? "enabled" : "disabled"); + printf("\tDirective Persistent Across Controller Level Resets \n"); + printf("\t\tIdentify Directive : %s\n", + (*(field + 32) & 0x1) ? "enabled" : "disabled"); + printf("\t\tStream Directive : %s\n", + (*(field + 32) & 0x2) ? "enabled" : "disabled"); + printf("\t\tData Placement Directive : %s\n", + (*(field + 32) & 0x4) ? "enabled" : "disabled"); + + break; + default: + fprintf(stderr, + "invalid directive operations for Identify Directives\n"); + } + break; + case NVME_DIRECTIVE_DTYPE_STREAMS: + switch (doper) { + case NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_PARAM: + printf("\tMax Streams Limit (MSL): %u\n", + *(__u16 *) field); + printf("\tNVM Subsystem Streams Available (NSSA): %u\n", + *(__u16 *) (field + 2)); + printf("\tNVM Subsystem Streams Open (NSSO): %u\n", + *(__u16 *) (field + 4)); + printf("\tNVM Subsystem Stream Capability (NSSC): %u\n", + *(__u16 *) (field + 6)); + printf("\tStream Write Size (in unit of LB size) (SWS): %u\n", + *(__u32 *) (field + 16)); + printf("\tStream Granularity Size (in unit of SWS) (SGS): %u\n", + *(__u16 *) (field + 20)); + printf("\tNamespace Streams Allocated (NSA): %u\n", + *(__u16 *) (field + 22)); + printf("\tNamespace Streams Open (NSO): %u\n", + *(__u16 *) (field + 24)); + break; + case NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_STATUS: + count = *(__u16 *) field; + printf("\tOpen Stream Count : %u\n", *(__u16 *) field); + for ( i = 0; i < count; i++ ) { + printf("\tStream Identifier %.6u : %u\n", i + 1, + *(__u16 *) (field + ((i + 1) * 2))); + } + break; + case NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_RESOURCE: + printf("\tNamespace Streams Allocated (NSA): %u\n", + result & 0xffff); + break; + default: + fprintf(stderr, + "invalid directive operations for Streams Directives\n"); + } + break; + default: + fprintf(stderr, "invalid directive type\n"); + break; + } + return; +} + +static void stdout_directive_show(__u8 type, __u8 oper, __u16 spec, __u32 nsid, __u32 result, + void *buf, __u32 len) +{ + printf("dir-receive: type:%#x operation:%#x spec:%#x nsid:%#x result:%#x\n", + type, oper, spec, nsid, result); + if (stdout_print_ops.flags & VERBOSE) + stdout_directive_show_fields(type, oper, result, buf); + else if (buf) + d(buf, len, 16, 1); +} + +static void stdout_lba_status_info(__u32 result) +{ + printf("\tLBA Status Information Poll Interval (LSIPI) : %u\n", (result >> 16) & 0xffff); + printf("\tLBA Status Information Report Interval (LSIRI): %u\n", result & 0xffff); +} + +static void stdout_plm_config(struct nvme_plm_config *plmcfg) +{ + printf("\tEnable Event :%04x\n", le16_to_cpu(plmcfg->ee)); + printf("\tDTWIN Reads Threshold :%"PRIu64"\n", le64_to_cpu(plmcfg->dtwinrt)); + printf("\tDTWIN Writes Threshold:%"PRIu64"\n", le64_to_cpu(plmcfg->dtwinwt)); + printf("\tDTWIN Time Threshold :%"PRIu64"\n", le64_to_cpu(plmcfg->dtwintt)); +} + +static void stdout_host_metadata(enum nvme_features_id fid, + struct nvme_host_metadata *data) +{ + struct nvme_metadata_element_desc *desc = &data->descs[0]; + int i; + char val[4096]; + __u16 len; + + printf("\tNum Metadata Element Descriptors: %d\n", data->ndesc); + for (i = 0; i < data->ndesc; i++) { + len = le16_to_cpu(desc->len); + strncpy(val, (char *)desc->val, min(sizeof(val) - 1, len)); + + printf("\tElement[%-3d]:\n", i); + printf("\t\tType : 0x%02x (%s)\n", desc->type, + nvme_host_metadata_type_to_string(fid, desc->type)); + printf("\t\tRevision : %d\n", desc->rev); + printf("\t\tLength : %d\n", len); + printf("\t\tValue : %s\n", val); + + desc = (struct nvme_metadata_element_desc *) + &desc->val[desc->len]; + } +} + +static void stdout_feature_show_fields(enum nvme_features_id fid, + unsigned int result, + unsigned char *buf) +{ + __u8 field; + uint64_t ull; + + switch (fid) { + case NVME_FEAT_FID_ARBITRATION: + printf("\tHigh Priority Weight (HPW): %u\n", ((result & 0xff000000) >> 24) + 1); + printf("\tMedium Priority Weight (MPW): %u\n", ((result & 0x00ff0000) >> 16) + 1); + printf("\tLow Priority Weight (LPW): %u\n", ((result & 0x0000ff00) >> 8) + 1); + printf("\tArbitration Burst (AB): "); + if ((result & 0x00000007) == 7) + printf("No limit\n"); + else + printf("%u\n", 1 << (result & 0x00000007)); + break; + case NVME_FEAT_FID_POWER_MGMT: + field = (result & 0x000000E0) >> 5; + printf("\tWorkload Hint (WH): %u - %s\n", field, nvme_feature_wl_hints_to_string(field)); + printf("\tPower State (PS): %u\n", result & 0x0000001f); + break; + case NVME_FEAT_FID_LBA_RANGE: + field = result & 0x0000003f; + printf("\tNumber of LBA Ranges (NUM): %u\n", field + 1); + if (buf) + stdout_lba_range((struct nvme_lba_range_type *)buf, field); + break; + case NVME_FEAT_FID_TEMP_THRESH: + field = (result & 0x00300000) >> 20; + printf("\tThreshold Type Select (THSEL): %u - %s\n", field, + nvme_feature_temp_type_to_string(field)); + field = (result & 0x000f0000) >> 16; + printf("\tThreshold Temperature Select (TMPSEL): %u - %s\n", + field, nvme_feature_temp_sel_to_string(field)); + printf("\tTemperature Threshold (TMPTH): %ld °C (%u K)\n", + kelvin_to_celsius(result & 0x0000ffff), result & 0x0000ffff); + break; + case NVME_FEAT_FID_ERR_RECOVERY: + printf("\tDeallocated or Unwritten Logical Block Error Enable (DULBE): %s\n", + ((result & 0x00010000) >> 16) ? "Enabled":"Disabled"); + printf("\tTime Limited Error Recovery (TLER): %u ms\n", + (result & 0x0000ffff) * 100); + break; + case NVME_FEAT_FID_VOLATILE_WC: + printf("\tVolatile Write Cache Enable (WCE): %s\n", (result & 0x00000001) ? "Enabled":"Disabled"); + break; + case NVME_FEAT_FID_NUM_QUEUES: + printf("\tNumber of IO Completion Queues Allocated (NCQA): %u\n", ((result & 0xffff0000) >> 16) + 1); + printf("\tNumber of IO Submission Queues Allocated (NSQA): %u\n", (result & 0x0000ffff) + 1); + break; + case NVME_FEAT_FID_IRQ_COALESCE: + printf("\tAggregation Time (TIME): %u usec\n", ((result & 0x0000ff00) >> 8) * 100); + printf("\tAggregation Threshold (THR): %u\n", (result & 0x000000ff) + 1); + break; + case NVME_FEAT_FID_IRQ_CONFIG: + printf("\tCoalescing Disable (CD): %s\n", ((result & 0x00010000) >> 16) ? "True":"False"); + printf("\tInterrupt Vector (IV): %u\n", result & 0x0000ffff); + break; + case NVME_FEAT_FID_WRITE_ATOMIC: + printf("\tDisable Normal (DN): %s\n", (result & 0x00000001) ? "True":"False"); + break; + case NVME_FEAT_FID_ASYNC_EVENT: + printf("\tDiscovery Log Page Change Notices : %s\n", + ((result & 0x80000000) >> 31) ? "Send async event":"Do not send async event"); + printf("\tEndurance Group Event Aggregate Log Change Notices : %s\n", + ((result & 0x00004000) >> 14) ? "Send async event":"Do not send async event"); + printf("\tLBA Status Information Notices : %s\n", + ((result & 0x00002000) >> 13) ? "Send async event":"Do not send async event"); + printf("\tPredictable Latency Event Aggregate Log Change Notices : %s\n", + ((result & 0x00001000) >> 12) ? "Send async event":"Do not send async event"); + printf("\tAsymmetric Namespace Access Change Notices : %s\n", + ((result & 0x00000800) >> 11) ? "Send async event":"Do not send async event"); + printf("\tTelemetry Log Notices : %s\n", + ((result & 0x00000400) >> 10) ? "Send async event":"Do not send async event"); + printf("\tFirmware Activation Notices : %s\n", + ((result & 0x00000200) >> 9) ? "Send async event":"Do not send async event"); + printf("\tNamespace Attribute Notices : %s\n", + ((result & 0x00000100) >> 8) ? "Send async event":"Do not send async event"); + printf("\tSMART / Health Critical Warnings : %s\n", + (result & 0x000000ff) ? "Send async event":"Do not send async event"); + break; + case NVME_FEAT_FID_AUTO_PST: + printf("\tAutonomous Power State Transition Enable (APSTE): %s\n", + (result & 0x00000001) ? "Enabled":"Disabled"); + if (buf) + stdout_auto_pst((struct nvme_feat_auto_pst *)buf); + break; + case NVME_FEAT_FID_HOST_MEM_BUF: + printf("\tEnable Host Memory (EHM): %s\n", (result & 0x00000001) ? "Enabled":"Disabled"); + if (buf) + stdout_host_mem_buffer((struct nvme_host_mem_buf_attrs *)buf); + break; + case NVME_FEAT_FID_TIMESTAMP: + if (buf) + stdout_timestamp((struct nvme_timestamp *)buf); + break; + case NVME_FEAT_FID_KATO: + printf("\tKeep Alive Timeout (KATO) in milliseconds: %u\n", result); + break; + case NVME_FEAT_FID_HCTM: + printf("\tThermal Management Temperature 1 (TMT1) : %u K (%ld °C)\n", + result >> 16, kelvin_to_celsius(result >> 16)); + printf("\tThermal Management Temperature 2 (TMT2) : %u K (%ld °C)\n", + result & 0x0000ffff, kelvin_to_celsius(result & 0x0000ffff)); + break; + case NVME_FEAT_FID_NOPSC: + printf("\tNon-Operational Power State Permissive Mode Enable (NOPPME): %s\n", + (result & 1) ? "True" : "False"); + break; + case NVME_FEAT_FID_RRL: + printf("\tRead Recovery Level (RRL): %u\n", result & 0xf); + break; + case NVME_FEAT_FID_PLM_CONFIG: + printf("\tPredictable Latency Window Enabled: %s\n", result & 0x1 ? "True":"False"); + if (buf) + stdout_plm_config((struct nvme_plm_config *)buf); + break; + case NVME_FEAT_FID_PLM_WINDOW: + printf("\tWindow Select: %s", nvme_plm_window_to_string(result)); + break; + case NVME_FEAT_FID_LBA_STS_INTERVAL: + stdout_lba_status_info(result); + break; + case NVME_FEAT_FID_HOST_BEHAVIOR: + if (buf) + printf("\tHost Behavior Support: %s\n", (buf[0] & 0x1) ? "True" : "False"); + break; + case NVME_FEAT_FID_SANITIZE: + printf("\tNo-Deallocate Response Mode (NODRM) : %u\n", result & 0x1); + break; + case NVME_FEAT_FID_ENDURANCE_EVT_CFG: + printf("\tEndurance Group Identifier (ENDGID): %u\n", result & 0xffff); + printf("\tEndurance Group Critical Warnings : %u\n", (result >> 16) & 0xff); + break; + case NVME_FEAT_FID_IOCS_PROFILE: + printf("\tI/O Command Set Profile: %s\n", result & 0x1 ? "True":"False"); + break; + case NVME_FEAT_FID_SPINUP_CONTROL: + printf("\tSpinup control feature Enabled: %s\n", (result & 1) ? "True" : "False"); + break; + case NVME_FEAT_FID_ENH_CTRL_METADATA: + case NVME_FEAT_FID_CTRL_METADATA: + case NVME_FEAT_FID_NS_METADATA: + if (buf) + stdout_host_metadata(fid, (struct nvme_host_metadata *)buf); + break; + case NVME_FEAT_FID_SW_PROGRESS: + printf("\tPre-boot Software Load Count (PBSLC): %u\n", result & 0x000000ff); + break; + case NVME_FEAT_FID_HOST_ID: + if (buf) { + ull = buf[7]; ull <<= 8; ull |= buf[6]; ull <<= 8; ull |= buf[5]; ull <<= 8; + ull |= buf[4]; ull <<= 8; ull |= buf[3]; ull <<= 8; ull |= buf[2]; ull <<= 8; + ull |= buf[1]; ull <<= 8; ull |= buf[0]; + printf("\tHost Identifier (HOSTID): %" PRIu64 "\n", ull); + } + break; + case NVME_FEAT_FID_RESV_MASK: + printf("\tMask Reservation Preempted Notification (RESPRE): %s\n", + ((result & 0x00000008) >> 3) ? "True":"False"); + printf("\tMask Reservation Released Notification (RESREL): %s\n", + ((result & 0x00000004) >> 2) ? "True":"False"); + printf("\tMask Registration Preempted Notification (REGPRE): %s\n", + ((result & 0x00000002) >> 1) ? "True":"False"); + break; + case NVME_FEAT_FID_RESV_PERSIST: + printf("\tPersist Through Power Loss (PTPL): %s\n", (result & 0x00000001) ? "True":"False"); + break; + case NVME_FEAT_FID_WRITE_PROTECT: + printf("\tNamespace Write Protect: %s\n", nvme_ns_wp_cfg_to_string(result)); + break; + case NVME_FEAT_FID_FDP: + printf("\tFlexible Direct Placement Enable (FDPE) : %s\n", + (result & 0x1) ? "Yes" : "No"); + printf("\tFlexible Direct Placement Configuration Index : %u\n", + (result >> 8) & 0xf); + break; + case NVME_FEAT_FID_FDP_EVENTS: + for (unsigned int i = 0; i < result; i++) { + struct nvme_fdp_supported_event_desc *d; + + d = &((struct nvme_fdp_supported_event_desc *)buf)[i]; + + printf("\t%-53s: %sEnabled\n", nvme_fdp_event_to_string(d->evt), + d->evta & 0x1 ? "" : "Not "); + } + default: + break; + } +} + +static void stdout_lba_status(struct nvme_lba_status *list, + unsigned long len) +{ + int idx; + + printf("Number of LBA Status Descriptors(NLSD): %" PRIu32 "\n", + le32_to_cpu(list->nlsd)); + printf("Completion Condition(CMPC): %u\n", list->cmpc); + + switch (list->cmpc) { + case 1: + printf("\tCompleted due to transferring the amount of data"\ + " specified in the MNDW field\n"); + break; + case 2: + printf("\tCompleted due to having performed the action\n"\ + "\tspecified in the Action Type field over the\n"\ + "\tnumber of logical blocks specified in the\n"\ + "\tRange Length field\n"); + break; + } + + for (idx = 0; idx < list->nlsd; idx++) { + struct nvme_lba_status_desc *e = &list->descs[idx]; + printf("{ DSLBA: 0x%016"PRIu64", NLB: 0x%08x, Status: 0x%02x }\n", + le64_to_cpu(e->dslba), le32_to_cpu(e->nlb), + e->status); + } +} + +static void stdout_dev_full_path(nvme_ns_t n, char *path, size_t len) +{ + struct stat st; + + snprintf(path, len, "/dev/%s", nvme_ns_get_name(n)); + if (stat(path, &st) == 0) + return; + + snprintf(path, len, "/dev/spdk/%s", nvme_ns_get_name(n)); + if (stat(path, &st) == 0) + return; + + /* + * We could start trying to search for it but let's make + * it simple and just don't show the path at all. + */ + snprintf(path, len, "%s", nvme_ns_get_name(n)); +} + +static void stdout_generic_full_path(nvme_ns_t n, char *path, size_t len) +{ + int head_instance; + int instance; + struct stat st; + + sscanf(nvme_ns_get_name(n), "nvme%dn%d", &instance, &head_instance); + snprintf(path, len, "/dev/ng%dn%d", instance, head_instance); + + if (stat(path, &st) == 0) + return; + + snprintf(path, len, "/dev/spdk/ng%dn%d", instance, head_instance); + if (stat(path, &st) == 0) + return; + /* + * We could start trying to search for it but let's make + * it simple and just don't show the path at all. + */ + snprintf(path, len, "ng%dn%d", instance, head_instance); +} + +static void stdout_list_item(nvme_ns_t n) +{ + char usage[128] = { 0 }, format[128] = { 0 }; + char devname[128] = { 0 }; char genname[128] = { 0 }; + + long long lba = nvme_ns_get_lba_size(n); + double nsze = nvme_ns_get_lba_count(n) * lba; + double nuse = nvme_ns_get_lba_util(n) * lba; + + const char *s_suffix = suffix_si_get(&nsze); + const char *u_suffix = suffix_si_get(&nuse); + const char *l_suffix = suffix_binary_get(&lba); + + snprintf(usage, sizeof(usage), "%6.2f %2sB / %6.2f %2sB", nuse, + u_suffix, nsze, s_suffix); + snprintf(format, sizeof(format), "%3.0f %2sB + %2d B", (double)lba, + l_suffix, nvme_ns_get_meta_size(n)); + + stdout_dev_full_path(n, devname, sizeof(devname)); + stdout_generic_full_path(n, genname, sizeof(genname)); + + printf("%-21s %-21s %-20s %-40s %#-10x %-26s %-16s %-8s\n", + devname, genname, nvme_ns_get_serial(n), + nvme_ns_get_model(n), nvme_ns_get_nsid(n), usage, format, + nvme_ns_get_firmware(n)); +} + +static void stdout_simple_list(nvme_root_t r) +{ + nvme_host_t h; + nvme_subsystem_t s; + nvme_ctrl_t c; + nvme_ns_t n; + + printf("%-21s %-21s %-20s %-40s %-10s %-26s %-16s %-8s\n", + "Node", "Generic", "SN", "Model", "Namespace", "Usage", "Format", "FW Rev"); + printf("%-.21s %-.21s %-.20s %-.40s %-.10s %-.26s %-.16s %-.8s\n", + dash, dash, dash, dash, dash, dash, dash, dash); + + nvme_for_each_host(r, h) { + nvme_for_each_subsystem(h, s) { + nvme_subsystem_for_each_ns(s, n) + stdout_list_item(n); + + nvme_subsystem_for_each_ctrl(s, c) + nvme_ctrl_for_each_ns(c, n) + stdout_list_item(n); + } + } +} + +static void stdout_ns_details(nvme_ns_t n) +{ + char usage[128] = { 0 }, format[128] = { 0 }; + char devname[128] = { 0 }, genname[128] = { 0 }; + + long long lba = nvme_ns_get_lba_size(n); + double nsze = nvme_ns_get_lba_count(n) * lba; + double nuse = nvme_ns_get_lba_util(n) * lba; + + const char *s_suffix = suffix_si_get(&nsze); + const char *u_suffix = suffix_si_get(&nuse); + const char *l_suffix = suffix_binary_get(&lba); + + sprintf(usage,"%6.2f %2sB / %6.2f %2sB", nuse, u_suffix, nsze, s_suffix); + sprintf(format,"%3.0f %2sB + %2d B", (double)lba, l_suffix, + nvme_ns_get_meta_size(n)); + + nvme_dev_full_path(n, devname, sizeof(devname)); + nvme_generic_full_path(n, genname, sizeof(genname)); + + printf("%-12s %-12s %#-10x %-26s %-16s ", devname, + genname, nvme_ns_get_nsid(n), usage, format); +} + +static void stdout_detailed_list(nvme_root_t r) +{ + nvme_host_t h; + nvme_subsystem_t s; + nvme_ctrl_t c; + nvme_path_t p; + nvme_ns_t n; + + printf("%-16s %-96s %-.16s\n", "Subsystem", "Subsystem-NQN", "Controllers"); + printf("%-.16s %-.96s %-.16s\n", dash, dash, dash); + + nvme_for_each_host(r, h) { + nvme_for_each_subsystem(h, s) { + bool first = true; + printf("%-16s %-96s ", nvme_subsystem_get_name(s), + nvme_subsystem_get_nqn(s)); + + nvme_subsystem_for_each_ctrl(s, c) { + printf("%s%s", first ? "": ", ", + nvme_ctrl_get_name(c)); + first = false; + } + printf("\n"); + } + } + printf("\n"); + + printf("%-8s %-20s %-40s %-8s %-6s %-14s %-12s %-16s\n", "Device", + "SN", "MN", "FR", "TxPort", "Address", "Subsystem", "Namespaces"); + printf("%-.8s %-.20s %-.40s %-.8s %-.6s %-.14s %-.12s %-.16s\n", dash, dash, + dash, dash, dash, dash, dash, dash); + + nvme_for_each_host(r, h) { + nvme_for_each_subsystem(h, s) { + nvme_subsystem_for_each_ctrl(s, c) { + bool first = true; + + printf("%-8s %-20s %-40s %-8s %-6s %-14s %-12s ", + nvme_ctrl_get_name(c), + nvme_ctrl_get_serial(c), + nvme_ctrl_get_model(c), + nvme_ctrl_get_firmware(c), + nvme_ctrl_get_transport(c), + nvme_ctrl_get_address(c), + nvme_subsystem_get_name(s)); + + nvme_ctrl_for_each_ns(c, n) { + printf("%s%s", first ? "": ", ", + nvme_ns_get_name(n)); + first = false; + } + + nvme_ctrl_for_each_path(c, p) { + n = nvme_path_get_ns(p); + if (!n) + continue; + printf("%s%s", first ? "": ", ", + nvme_ns_get_name(n)); + first = false; + } + printf("\n"); + } + } + } + printf("\n"); + + printf("%-12s %-12s %-10s %-26s %-16s %-16s\n", "Device", "Generic", + "NSID", "Usage", "Format", "Controllers"); + printf("%-.12s %-.12s %-.10s %-.26s %-.16s %-.16s\n", dash, dash, dash, + dash, dash, dash); + + nvme_for_each_host(r, h) { + nvme_for_each_subsystem(h, s) { + nvme_subsystem_for_each_ctrl(s, c) { + nvme_ctrl_for_each_ns(c, n) { + stdout_ns_details(n); + printf("%s\n", nvme_ctrl_get_name(c)); + } + } + + nvme_subsystem_for_each_ns(s, n) { + bool first = true; + + stdout_ns_details(n); + nvme_subsystem_for_each_ctrl(s, c) { + printf("%s%s", first ? "" : ", ", + nvme_ctrl_get_name(c)); + first = false; + } + printf("\n"); + } + } + } +} + +static void stdout_list_items(nvme_root_t r) +{ + if (stdout_print_ops.flags & VERBOSE) + stdout_detailed_list(r); + else + stdout_simple_list(r); +} + +static bool nvme_is_multipath(nvme_subsystem_t s) +{ + nvme_ns_t n; + nvme_path_t p; + + nvme_subsystem_for_each_ns(s, n) + nvme_namespace_for_each_path(n, p) + return true; + + return false; +} + +static void stdout_subsystem_topology_multipath(nvme_subsystem_t s, + enum nvme_cli_topo_ranking ranking) +{ + nvme_ns_t n; + nvme_path_t p; + nvme_ctrl_t c; + + if (ranking == NVME_CLI_TOPO_NAMESPACE) { + nvme_subsystem_for_each_ns(s, n) { + printf(" +- ns %d\n", nvme_ns_get_nsid(n)); + printf(" \\\n"); + + nvme_namespace_for_each_path(n, p) { + c = nvme_path_get_ctrl(p); + + printf(" +- %s %s %s %s %s\n", + nvme_ctrl_get_name(c), + nvme_ctrl_get_transport(c), + nvme_ctrl_get_address(c), + nvme_ctrl_get_state(c), + nvme_path_get_ana_state(p)); + } + } + } else { + /* NVME_CLI_TOPO_CTRL */ + nvme_subsystem_for_each_ctrl(s, c) { + printf(" +- %s %s %s\n", + nvme_ctrl_get_name(c), + nvme_ctrl_get_transport(c), + nvme_ctrl_get_address(c)); + printf(" \\\n"); + + nvme_subsystem_for_each_ns(s, n) { + nvme_namespace_for_each_path(n, p) { + if (nvme_path_get_ctrl(p) != c) + continue; + + printf(" +- ns %d %s %s\n", + nvme_ns_get_nsid(n), + nvme_ctrl_get_state(c), + nvme_path_get_ana_state(p)); + } + } + } + } +} + +static void stdout_subsystem_topology(nvme_subsystem_t s, + enum nvme_cli_topo_ranking ranking) +{ + nvme_ctrl_t c; + nvme_ns_t n; + + if (ranking == NVME_CLI_TOPO_NAMESPACE) { + nvme_subsystem_for_each_ctrl(s, c) { + nvme_ctrl_for_each_ns(c, n) { + printf(" +- ns %d\n", nvme_ns_get_nsid(n)); + printf(" \\\n"); + printf(" +- %s %s %s %s\n", + nvme_ctrl_get_name(c), + nvme_ctrl_get_transport(c), + nvme_ctrl_get_address(c), + nvme_ctrl_get_state(c)); + } + } + } else { + /* NVME_CLI_TOPO_CTRL */ + nvme_subsystem_for_each_ctrl(s, c) { + printf(" +- %s %s %s\n", + nvme_ctrl_get_name(c), + nvme_ctrl_get_transport(c), + nvme_ctrl_get_address(c)); + printf(" \\\n"); + nvme_ctrl_for_each_ns(c, n) { + printf(" +- ns %d %s\n", + nvme_ns_get_nsid(n), + nvme_ctrl_get_state(c)); + } + } + } +} + +static void stdout_simple_topology(nvme_root_t r, + enum nvme_cli_topo_ranking ranking) +{ + nvme_host_t h; + nvme_subsystem_t s; + + nvme_for_each_host(r, h) { + nvme_for_each_subsystem(h, s) { + + printf("%s - NQN=%s\n", nvme_subsystem_get_name(s), + nvme_subsystem_get_nqn(s)); + printf("\\\n"); + + if (nvme_is_multipath(s)) + stdout_subsystem_topology_multipath(s, ranking); + else + stdout_subsystem_topology(s, ranking); + } + } +} + +static void stdout_topology_namespace(nvme_root_t r) +{ + stdout_simple_topology(r, NVME_CLI_TOPO_NAMESPACE); +} + +static void stdout_topology_ctrl(nvme_root_t r) +{ + stdout_simple_topology(r, NVME_CLI_TOPO_CTRL); +} + +static void stdout_message(bool error, const char *msg, va_list ap) +{ + vfprintf(error ? stderr : stdout, msg, ap); + + printf("\n"); +} + +static void stdout_perror(const char *msg) +{ + perror(msg); +} + +static void stdout_discovery_log(struct nvmf_discovery_log *log, int numrec) +{ + int i; + + printf("\nDiscovery Log Number of Records %d, Generation counter %"PRIu64"\n", + numrec, le64_to_cpu(log->genctr)); + + for (i = 0; i < numrec; i++) { + struct nvmf_disc_log_entry *e = &log->entries[i]; + + printf("=====Discovery Log Entry %d======\n", i); + printf("trtype: %s\n", nvmf_trtype_str(e->trtype)); + printf("adrfam: %s\n", + strlen(e->traddr) ? + nvmf_adrfam_str(e->adrfam) : ""); + printf("subtype: %s\n", nvmf_subtype_str(e->subtype)); + printf("treq: %s\n", nvmf_treq_str(e->treq)); + printf("portid: %d\n", le16_to_cpu(e->portid)); + printf("trsvcid: %s\n", e->trsvcid); + printf("subnqn: %s\n", e->subnqn); + printf("traddr: %s\n", e->traddr); + printf("eflags: %s\n", + nvmf_eflags_str(le16_to_cpu(e->eflags))); + + switch (e->trtype) { + case NVMF_TRTYPE_RDMA: + printf("rdma_prtype: %s\n", + nvmf_prtype_str(e->tsas.rdma.prtype)); + printf("rdma_qptype: %s\n", + nvmf_qptype_str(e->tsas.rdma.qptype)); + printf("rdma_cms: %s\n", + nvmf_cms_str(e->tsas.rdma.cms)); + printf("rdma_pkey: 0x%04x\n", + le16_to_cpu(e->tsas.rdma.pkey)); + break; + case NVMF_TRTYPE_TCP: + printf("sectype: %s\n", + nvmf_sectype_str(e->tsas.tcp.sectype)); + break; + } + } +} + +static void stdout_connect_msg(nvme_ctrl_t c) +{ + printf("device: %s\n", nvme_ctrl_get_name(c)); +} + +static struct print_ops stdout_print_ops = { + .ana_log = stdout_ana_log, + .boot_part_log = stdout_boot_part_log, + .ctrl_list = stdout_list_ctrl, + .ctrl_registers = stdout_ctrl_registers, + .directive = stdout_directive_show, + .discovery_log = stdout_discovery_log, + .effects_log_list = stdout_effects_log_pages, + .endurance_group_event_agg_log = stdout_endurance_group_event_agg_log, + .endurance_group_list = stdout_endurance_group_list, + .endurance_log = stdout_endurance_log, + .error_log = stdout_error_log, + .fdp_config_log = stdout_fdp_configs, + .fdp_event_log = stdout_fdp_events, + .fdp_ruh_status = stdout_fdp_ruh_status, + .fdp_stats_log = stdout_fdp_stats, + .fdp_usage_log = stdout_fdp_usage, + .fid_supported_effects_log = stdout_fid_support_effects_log, + .fw_log = stdout_fw_log, + .id_ctrl = stdout_id_ctrl, + .id_ctrl_nvm = stdout_id_ctrl_nvm, + .id_ctrl_rpmbs = stdout_id_ctrl_rpmbs, + .id_domain_list = stdout_id_domain_list, + .id_independent_id_ns = stdout_cmd_set_independent_id_ns, + .id_iocs = stdout_id_iocs, + .id_ns = stdout_id_ns, + .id_ns_descs = stdout_id_ns_descs, + .id_ns_granularity_list = stdout_id_ns_granularity_list, + .id_nvmset_list = stdout_id_nvmset, + .id_uuid_list = stdout_id_uuid_list, + .lba_range = stdout_lba_range, + .lba_status = stdout_lba_status, + .lba_status_info = stdout_lba_status_info, + .lba_status_log = stdout_lba_status_log, + .media_unit_stat_log = stdout_media_unit_stat_log, + .mi_cmd_support_effects_log = stdout_mi_cmd_support_effects_log, + .ns_list = stdout_list_ns, + .ns_list_log = stdout_changed_ns_list_log, + .nvm_id_ns = stdout_nvm_id_ns, + .persistent_event_log = stdout_persistent_event_log, + .predictable_latency_event_agg_log = stdout_predictable_latency_event_agg_log, + .predictable_latency_per_nvmset = stdout_predictable_latency_per_nvmset, + .primary_ctrl_cap = stdout_primary_ctrl_cap, + .resv_notification_log = stdout_resv_notif_log, + .resv_report = stdout_resv_report, + .sanitize_log_page = stdout_sanitize_log, + .secondary_ctrl_list = stdout_list_secondary_ctrl, + .select_result = stdout_select_result, + .self_test_log = stdout_self_test_log, + .show_feature_fields = stdout_feature_show_fields, + .single_property = stdout_single_property, + .smart_log = stdout_smart_log, + .supported_cap_config_list_log = stdout_supported_cap_config_log, + .supported_log_pages = stdout_supported_log, + .zns_changed_zone_log = stdout_zns_changed, + .zns_id_ctrl = stdout_zns_id_ctrl, + .zns_id_ns = stdout_zns_id_ns, + .zns_report_zones = stdout_zns_report_zones, + + .list_items = stdout_list_items, + .print_nvme_subsystem_list = stdout_subsystem_list, + .topology_ctrl = stdout_topology_ctrl, + .topology_namespace = stdout_topology_namespace, + + .show_status = stdout_status, + .show_message = stdout_message, + .show_perror = stdout_perror, + .connect_msg = stdout_connect_msg, +}; + +struct print_ops *nvme_get_stdout_print_ops(enum nvme_print_flags flags) +{ + stdout_print_ops.flags = flags; + return &stdout_print_ops; +} diff --git a/nvme-print.c b/nvme-print.c index f036eff5..c74e117a 100644 --- a/nvme-print.c +++ b/nvme-print.c @@ -15,19 +15,6 @@ #include "util/types.h" #include "common.h" -static const uint8_t zero_uuid[16] = { 0 }; -static const uint8_t invalid_uuid[16] = {[0 ... 15] = 0xff }; -static const char dash[100] = {[0 ... 99] = '-'}; - -struct nvme_bar_cap { - __u16 mqes; - __u8 ams_cqr; - __u8 to; - __u16 bps_css_nssrs_dstrd; - __u8 mpsmax_mpsmin; - __u8 rsvd_crms_nsss_cmbs_pmrs; -}; - #define nvme_print(name, flags, ...) \ do { \ struct print_ops *ops = nvme_print_ops(flags); \ @@ -44,6 +31,8 @@ static struct print_ops *nvme_print_ops(enum nvme_print_flags flags) if (flags & JSON) ops = nvme_get_json_print_ops(flags); + else if (!(flags & BINARY)) + ops = nvme_get_stdout_print_ops(flags); return ops; } @@ -151,30 +140,6 @@ void nvme_show_predictable_latency_per_nvmset( if (flags & BINARY) return d_raw((unsigned char *)plpns_log, sizeof(*plpns_log)); - - printf("Predictable Latency Per NVM Set Log for device: %s\n", - devname); - printf("Predictable Latency Per NVM Set Log for NVM Set ID: %u\n", - le16_to_cpu(nvmset_id)); - printf("Status: %u\n", plpns_log->status); - printf("Event Type: %u\n", - le16_to_cpu(plpns_log->event_type)); - printf("DTWIN Reads Typical: %"PRIu64"\n", - le64_to_cpu(plpns_log->dtwin_rt)); - printf("DTWIN Writes Typical: %"PRIu64"\n", - le64_to_cpu(plpns_log->dtwin_wt)); - printf("DTWIN Time Maximum: %"PRIu64"\n", - le64_to_cpu(plpns_log->dtwin_tmax)); - printf("NDWIN Time Minimum High: %"PRIu64" \n", - le64_to_cpu(plpns_log->ndwin_tmin_hi)); - printf("NDWIN Time Minimum Low: %"PRIu64"\n", - le64_to_cpu(plpns_log->ndwin_tmin_lo)); - printf("DTWIN Reads Estimate: %"PRIu64"\n", - le64_to_cpu(plpns_log->dtwin_re)); - printf("DTWIN Writes Estimate: %"PRIu64"\n", - le64_to_cpu(plpns_log->dtwin_we)); - printf("DTWIN Time Estimate: %"PRIu64"\n\n\n", - le64_to_cpu(plpns_log->dtwin_te)); } void nvme_show_predictable_latency_event_agg_log( @@ -182,27 +147,11 @@ void nvme_show_predictable_latency_event_agg_log( __u64 log_entries, __u32 size, const char *devname, enum nvme_print_flags flags) { - __u64 num_iter; - __u64 num_entries; - nvme_print(predictable_latency_event_agg_log, flags, pea_log, log_entries, size, devname); if (flags & BINARY) return d_raw((unsigned char *)pea_log, size); - - num_entries = le64_to_cpu(pea_log->num_entries); - printf("Predictable Latency Event Aggregate Log for"\ - " device: %s\n", devname); - - printf("Number of Entries Available: %"PRIu64"\n", - (uint64_t)num_entries); - - num_iter = min(num_entries, log_entries); - for (int i = 0; i < num_iter; i++) { - printf("Entry[%d]: %u\n", i + 1, - le16_to_cpu(pea_log->entries[i])); - } } const char *nvme_pel_event_to_string(int type) @@ -255,316 +204,15 @@ const char *nvme_nss_hw_error_to_string(__u16 error_code) } } -static void nvme_show_persistent_event_log_rci(__le32 pel_header_rci) -{ - __u32 rci = le32_to_cpu(pel_header_rci); - __u32 rsvd19 = (rci & 0xfff80000) >> 19; - __u8 rce = (rci & 0x40000) >> 18; - __u8 rcpit = (rci & 0x30000) >> 16; - __u16 rcpid = rci & 0xffff; - - if(rsvd19) - printf(" [31:19] : %#x\tReserved\n", rsvd19); - printf("\tReporting Context Exists (RCE): %s(%u)\n", - rce ? "true" : "false", rce); - printf("\tReporting Context Port Identifier Type (RCPIT): %u(%s)\n", rcpit, - (rcpit == 0x00) ? "Does not already exist" : - (rcpit == 0x01) ? "NVM subsystem port" : - (rcpit == 0x02) ? "NVMe-MI port" : "Reserved"); - printf("\tReporting Context Port Identifier (RCPID): %#x\n\n", rcpid); -} - -static void nvme_show_persistent_event_entry_ehai(__u8 ehai) -{ - __u8 rsvd1 = (ehai & 0xfc) >> 2; - __u8 pit = ehai & 0x03; - - printf(" [7:2] : %#x\tReserved\n", rsvd1); - printf("\tPort Identifier Type (PIT): %u(%s)\n", pit, - (pit == 0x00) ? "PIT not reported and PELPID does not apply" : - (pit == 0x01) ? "NVM subsystem port" : - (pit == 0x02) ? "NVMe-MI port" : - "Event not associated with any port and PELPID does not apply"); -} - -static void add_bitmap(int i, __u8 seb) -{ - for (int bit = 0; bit < 8; bit++) { - if (nvme_pel_event_to_string(bit + i * 8)) { - if (nvme_pel_event_to_string(bit + i * 8)) - if ((seb >> bit) & 0x1) - printf(" Support %s\n", - nvme_pel_event_to_string(bit + i * 8)); - } - } -} - void nvme_show_persistent_event_log(void *pevent_log_info, __u8 action, __u32 size, const char *devname, enum nvme_print_flags flags) { - __u32 offset, por_info_len, por_info_list; - __u64 *fw_rev; - int fid, cdw11, dword_cnt; - unsigned char *mem_buf = NULL; - struct nvme_smart_log *smart_event; - struct nvme_fw_commit_event *fw_commit_event; - struct nvme_time_stamp_change_event *ts_change_event; - struct nvme_power_on_reset_info_list *por_event; - struct nvme_nss_hw_err_event *nss_hw_err_event; - struct nvme_change_ns_event *ns_event; - struct nvme_format_nvm_start_event *format_start_event; - struct nvme_format_nvm_compln_event *format_cmpln_event; - struct nvme_sanitize_start_event *sanitize_start_event; - struct nvme_sanitize_compln_event *sanitize_cmpln_event; - struct nvme_set_feature_event *set_feat_event; - struct nvme_thermal_exc_event *thermal_exc_event; - struct nvme_persistent_event_log *pevent_log_head; - struct nvme_persistent_event_entry *pevent_entry_head; - int human = flags & VERBOSE; - nvme_print(persistent_event_log, flags, pevent_log_info, action, size, devname); if (flags & BINARY) return d_raw((unsigned char *)pevent_log_info, size); - - offset = sizeof(*pevent_log_head); - - printf("Persistent Event Log for device: %s\n", devname); - printf("Action for Persistent Event Log: %u\n", action); - if (size >= offset) { - pevent_log_head = pevent_log_info; - printf("Log Identifier: %u\n", pevent_log_head->lid); - printf("Total Number of Events: %u\n", - le32_to_cpu(pevent_log_head->tnev)); - printf("Total Log Length : %"PRIu64"\n", - le64_to_cpu(pevent_log_head->tll)); - printf("Log Revision: %u\n", pevent_log_head->rv); - printf("Log Header Length: %u\n", pevent_log_head->lhl); - printf("Timestamp: %"PRIu64"\n", - le64_to_cpu(pevent_log_head->ts)); - printf("Power On Hours (POH): %s", - uint128_t_to_l10n_string(le128_to_cpu(pevent_log_head->poh))); - printf("Power Cycle Count: %"PRIu64"\n", - le64_to_cpu(pevent_log_head->pcc)); - printf("PCI Vendor ID (VID): %u\n", - le16_to_cpu(pevent_log_head->vid)); - printf("PCI Subsystem Vendor ID (SSVID): %u\n", - le16_to_cpu(pevent_log_head->ssvid)); - printf("Serial Number (SN): %-.*s\n", - (int)sizeof(pevent_log_head->sn), pevent_log_head->sn); - printf("Model Number (MN): %-.*s\n", - (int)sizeof(pevent_log_head->mn), pevent_log_head->mn); - printf("NVM Subsystem NVMe Qualified Name (SUBNQN): %-.*s\n", - (int)sizeof(pevent_log_head->subnqn), - pevent_log_head->subnqn); - printf("Generation Number: %u\n", - le16_to_cpu(pevent_log_head->gen_number)); - printf("Reporting Context Information (RCI): %u\n", - le32_to_cpu(pevent_log_head->rci)); - if (human) - nvme_show_persistent_event_log_rci(pevent_log_head->rci); - printf("Supported Events Bitmap: \n"); - for (int i = 0; i < 32; i++) { - if (pevent_log_head->seb[i] == 0) - continue; - add_bitmap(i, pevent_log_head->seb[i]); - } - } else { - printf("No log data can be shown with this log len at least " \ - "512 bytes is required or can be 0 to read the complete "\ - "log page after context established\n"); - return; - } - printf("\n"); - printf("\nPersistent Event Entries:\n"); - for (int i = 0; i < le32_to_cpu(pevent_log_head->tnev); i++) { - if (offset + sizeof(*pevent_entry_head) >= size) - break; - - pevent_entry_head = pevent_log_info + offset; - - if ((offset + pevent_entry_head->ehl + 3 + - le16_to_cpu(pevent_entry_head->el)) >= size) - break; - printf("Event Number: %u\n", i); - printf("Event Type: %s\n", nvme_pel_event_to_string(pevent_entry_head->etype)); - printf("Event Type Revision: %u\n", pevent_entry_head->etype_rev); - printf("Event Header Length: %u\n", pevent_entry_head->ehl); - printf("Event Header Additional Info: %u\n", pevent_entry_head->ehai); - if (human) - nvme_show_persistent_event_entry_ehai(pevent_entry_head->ehai); - printf("Controller Identifier: %u\n", - le16_to_cpu(pevent_entry_head->cntlid)); - printf("Event Timestamp: %"PRIu64"\n", - le64_to_cpu(pevent_entry_head->ets)); - printf("Port Identifier: %u\n", - le16_to_cpu(pevent_entry_head->pelpid)); - printf("Vendor Specific Information Length: %u\n", - le16_to_cpu(pevent_entry_head->vsil)); - printf("Event Length: %u\n", le16_to_cpu(pevent_entry_head->el)); - - offset += pevent_entry_head->ehl + 3; - - switch (pevent_entry_head->etype) { - case NVME_PEL_SMART_HEALTH_EVENT: - smart_event = pevent_log_info + offset; - printf("Smart Health Event Entry: \n"); - nvme_show_smart_log(smart_event, NVME_NSID_ALL, devname, flags); - break; - case NVME_PEL_FW_COMMIT_EVENT: - fw_commit_event = pevent_log_info + offset; - printf("FW Commit Event Entry: \n"); - printf("Old Firmware Revision: %"PRIu64" (%s)\n", - le64_to_cpu(fw_commit_event->old_fw_rev), - util_fw_to_string((char *)&fw_commit_event->old_fw_rev)); - printf("New Firmware Revision: %"PRIu64" (%s)\n", - le64_to_cpu(fw_commit_event->new_fw_rev), - util_fw_to_string((char *)&fw_commit_event->new_fw_rev)); - printf("FW Commit Action: %u\n", - fw_commit_event->fw_commit_action); - printf("FW Slot: %u\n", fw_commit_event->fw_slot); - printf("Status Code Type for Firmware Commit Command: %u\n", - fw_commit_event->sct_fw); - printf("Status Returned for Firmware Commit Command: %u\n", - fw_commit_event->sc_fw); - printf("Vendor Assigned Firmware Commit Result Code: %u\n", - le16_to_cpu(fw_commit_event->vndr_assign_fw_commit_rc)); - break; - case NVME_PEL_TIMESTAMP_EVENT: - ts_change_event = pevent_log_info + offset; - printf("Time Stamp Change Event Entry: \n"); - printf("Previous Timestamp: %"PRIu64"\n", - le64_to_cpu(ts_change_event->previous_timestamp)); - printf("Milliseconds Since Reset: %"PRIu64"\n", - le64_to_cpu(ts_change_event->ml_secs_since_reset)); - break; - case NVME_PEL_POWER_ON_RESET_EVENT: - por_info_len = (le16_to_cpu(pevent_entry_head->el) - - le16_to_cpu(pevent_entry_head->vsil) - sizeof(*fw_rev)); - - por_info_list = por_info_len / sizeof(*por_event); - - printf("Power On Reset Event Entry: \n"); - fw_rev = pevent_log_info + offset; - printf("Firmware Revision: %"PRIu64" (%s)\n", le64_to_cpu(*fw_rev), - util_fw_to_string((char *)fw_rev)); - printf("Reset Information List: \n"); - - for (int i = 0; i < por_info_list; i++) { - por_event = pevent_log_info + offset + - sizeof(*fw_rev) + i * sizeof(*por_event); - printf("Controller ID: %u\n", le16_to_cpu(por_event->cid)); - printf("Firmware Activation: %u\n", - por_event->fw_act); - printf("Operation in Progress: %u\n", - por_event->op_in_prog); - printf("Controller Power Cycle: %u\n", - le32_to_cpu(por_event->ctrl_power_cycle)); - printf("Power on milliseconds: %"PRIu64"\n", - le64_to_cpu(por_event->power_on_ml_seconds)); - printf("Controller Timestamp: %"PRIu64"\n", - le64_to_cpu(por_event->ctrl_time_stamp)); - } - break; - case NVME_PEL_NSS_HW_ERROR_EVENT: - nss_hw_err_event = pevent_log_info + offset; - printf("NVM Subsystem Hardware Error Event Code Entry: %u, %s\n", - le16_to_cpu(nss_hw_err_event->nss_hw_err_event_code), - nvme_nss_hw_error_to_string(nss_hw_err_event->nss_hw_err_event_code)); - break; - case NVME_PEL_CHANGE_NS_EVENT: - ns_event = pevent_log_info + offset; - printf("Change Namespace Event Entry: \n"); - printf("Namespace Management CDW10: %u\n", - le32_to_cpu(ns_event->nsmgt_cdw10)); - printf("Namespace Size: %"PRIu64"\n", - le64_to_cpu(ns_event->nsze)); - printf("Namespace Capacity: %"PRIu64"\n", - le64_to_cpu(ns_event->nscap)); - printf("Formatted LBA Size: %u\n", ns_event->flbas); - printf("End-to-end Data Protection Type Settings: %u\n", - ns_event->dps); - printf("Namespace Multi-path I/O and Namespace Sharing" \ - " Capabilities: %u\n", ns_event->nmic); - printf("ANA Group Identifier: %u\n", - le32_to_cpu(ns_event->ana_grp_id)); - printf("NVM Set Identifier: %u\n", le16_to_cpu(ns_event->nvmset_id)); - printf("Namespace ID: %u\n", le32_to_cpu(ns_event->nsid)); - break; - case NVME_PEL_FORMAT_START_EVENT: - format_start_event = pevent_log_info + offset; - printf("Format NVM Start Event Entry: \n"); - printf("Namespace Identifier: %u\n", - le32_to_cpu(format_start_event->nsid)); - printf("Format NVM Attributes: %u\n", - format_start_event->fna); - printf("Format NVM CDW10: %u\n", - le32_to_cpu(format_start_event->format_nvm_cdw10)); - break; - case NVME_PEL_FORMAT_COMPLETION_EVENT: - format_cmpln_event = pevent_log_info + offset; - printf("Format NVM Completion Event Entry: \n"); - printf("Namespace Identifier: %u\n", - le32_to_cpu(format_cmpln_event->nsid)); - printf("Smallest Format Progress Indicator: %u\n", - format_cmpln_event->smallest_fpi); - printf("Format NVM Status: %u\n", - format_cmpln_event->format_nvm_status); - printf("Completion Information: %u\n", - le16_to_cpu(format_cmpln_event->compln_info)); - printf("Status Field: %u\n", - le32_to_cpu(format_cmpln_event->status_field)); - break; - case NVME_PEL_SANITIZE_START_EVENT: - sanitize_start_event = pevent_log_info + offset; - printf("Sanitize Start Event Entry: \n"); - printf("SANICAP: %u\n", sanitize_start_event->sani_cap); - printf("Sanitize CDW10: %u\n", - le32_to_cpu(sanitize_start_event->sani_cdw10)); - printf("Sanitize CDW11: %u\n", - le32_to_cpu(sanitize_start_event->sani_cdw11)); - break; - case NVME_PEL_SANITIZE_COMPLETION_EVENT: - sanitize_cmpln_event = pevent_log_info + offset; - printf("Sanitize Completion Event Entry: \n"); - printf("Sanitize Progress: %u\n", - le16_to_cpu(sanitize_cmpln_event->sani_prog)); - printf("Sanitize Status: %u\n", - le16_to_cpu(sanitize_cmpln_event->sani_status)); - printf("Completion Information: %u\n", - le16_to_cpu(sanitize_cmpln_event->cmpln_info)); - break; - case NVME_PEL_SET_FEATURE_EVENT: - set_feat_event = pevent_log_info + offset; - printf("Set Feature Event Entry: \n"); - dword_cnt = set_feat_event->layout & 0x03; - fid = le32_to_cpu(set_feat_event->cdw_mem[0]) & 0x000f; - cdw11 = le32_to_cpu(set_feat_event->cdw_mem[1]); - - printf("Set Feature ID :%#02x (%s), value:%#08x\n", fid, - nvme_feature_to_string(fid), cdw11); - if (((set_feat_event->layout & 0xff) >> 2) != 0) { - mem_buf = (unsigned char *)(set_feat_event + 4 + dword_cnt * 4); - nvme_feature_show_fields(fid, cdw11, mem_buf); - } - break; - case NVME_PEL_TELEMETRY_CRT: - d(pevent_log_info + offset, 512, 16, 1); - break; - case NVME_PEL_THERMAL_EXCURSION_EVENT: - thermal_exc_event = pevent_log_info + offset; - printf("Thermal Excursion Event Entry: \n"); - printf("Over Temperature: %u\n", thermal_exc_event->over_temp); - printf("Threshold: %u\n", thermal_exc_event->threshold); - break; - default: - printf("Reserved Event\n\n"); - } - offset += le16_to_cpu(pevent_entry_head->el); - printf("\n"); - } } void nvme_show_endurance_group_event_agg_log( @@ -577,66 +225,15 @@ void nvme_show_endurance_group_event_agg_log( if (flags & BINARY) return d_raw((unsigned char *)endurance_log, size); - - printf("Endurance Group Event Aggregate Log for"\ - " device: %s\n", devname); - - printf("Number of Entries Available: %"PRIu64"\n", - le64_to_cpu(endurance_log->num_entries)); - - for (int i = 0; i < log_entries; i++) { - printf("Entry[%d]: %u\n", i + 1, - le16_to_cpu(endurance_log->entries[i])); - } } void nvme_show_lba_status_log(void *lba_status, __u32 size, const char *devname, enum nvme_print_flags flags) { - struct nvme_lba_status_log *hdr; - struct nvme_lbas_ns_element *ns_element; - struct nvme_lba_rd *range_desc; - int offset = sizeof(*hdr); - __u32 num_lba_desc, num_elements; - nvme_print(lba_status_log, flags, lba_status, size, devname); if (flags & BINARY) return d_raw((unsigned char *)lba_status, size); - - hdr = lba_status; - printf("LBA Status Log for device: %s\n", devname); - printf("LBA Status Log Page Length: %"PRIu32"\n", - le32_to_cpu(hdr->lslplen)); - num_elements = le32_to_cpu(hdr->nlslne); - printf("Number of LBA Status Log Namespace Elements: %"PRIu32"\n", - num_elements); - printf("Estimate of Unrecoverable Logical Blocks: %"PRIu32"\n", - le32_to_cpu(hdr->estulb)); - printf("LBA Status Generation Counter: %"PRIu16"\n", le16_to_cpu(hdr->lsgc)); - for (int ele = 0; ele < num_elements; ele++) { - ns_element = lba_status + offset; - printf("Namespace Element Identifier: %"PRIu32"\n", - le32_to_cpu(ns_element->neid)); - num_lba_desc = le32_to_cpu(ns_element->nlrd); - printf("Number of LBA Range Descriptors: %"PRIu32"\n", num_lba_desc); - printf("Recommended Action Type: %u\n", ns_element->ratype); - - offset += sizeof(*ns_element); - if (num_lba_desc != 0xffffffff) { - for (int i = 0; i < num_lba_desc; i++) { - range_desc = lba_status + offset; - printf("RSLBA[%d]: %"PRIu64"\n", i, - le64_to_cpu(range_desc->rslba)); - printf("RNLB[%d]: %"PRIu32"\n", i, - le32_to_cpu(range_desc->rnlb)); - offset += sizeof(*range_desc); - } - } else { - printf("Number of LBA Range Descriptors (NLRD) set to %#x for "\ - "NS element %d\n", num_lba_desc, ele); - } - } } const char *nvme_resv_notif_to_string(__u8 type) @@ -657,219 +254,52 @@ void nvme_show_resv_notif_log(struct nvme_resv_notification_log *resv, if (flags & BINARY) return d_raw((unsigned char *)resv, sizeof(*resv)); - - printf("Reservation Notif Log for device: %s\n", devname); - printf("Log Page Count : %"PRIx64"\n", - le64_to_cpu(resv->lpc)); - printf("Resv Notif Log Page Type : %u (%s)\n", - resv->rnlpt, - nvme_resv_notif_to_string(resv->rnlpt)); - printf("Num of Available Log Pages : %u\n", resv->nalp); - printf("Namespace ID: : %"PRIx32"\n", - le32_to_cpu(resv->nsid)); -} - -static void nvme_show_fid_support_effects_log_human(__u32 fid_support) -{ - const char *set = "+"; - const char *clr = "-"; - __u16 fsp; - - printf(" FSUPP+"); - printf(" UDCC%s", (fid_support & NVME_FID_SUPPORTED_EFFECTS_UDCC) ? set : clr); - printf(" NCC%s", (fid_support & NVME_FID_SUPPORTED_EFFECTS_NCC) ? set : clr); - printf(" NIC%s", (fid_support & NVME_FID_SUPPORTED_EFFECTS_NIC) ? set : clr); - printf(" CCC%s", (fid_support & NVME_FID_SUPPORTED_EFFECTS_CCC) ? set : clr); - printf(" USS%s", (fid_support & NVME_FID_SUPPORTED_EFFECTS_UUID_SEL) ? set : clr); - - fsp = (fid_support >> NVME_FID_SUPPORTED_EFFECTS_SCOPE_SHIFT) & NVME_FID_SUPPORTED_EFFECTS_SCOPE_MASK; - - printf(" NAMESPACE SCOPE%s", (fsp & NVME_FID_SUPPORTED_EFFECTS_SCOPE_NS) ? set : clr); - printf(" CONTROLLER SCOPE%s", (fsp & NVME_FID_SUPPORTED_EFFECTS_SCOPE_CTRL) ? set : clr); - printf(" NVM SET SCOPE%s", (fsp & NVME_FID_SUPPORTED_EFFECTS_SCOPE_NVM_SET) ? set : clr); - printf(" ENDURANCE GROUP SCOPE%s", (fsp & NVME_FID_SUPPORTED_EFFECTS_SCOPE_ENDGRP) ? set : clr); - printf(" DOMAIN SCOPE%s", (fsp & NVME_FID_SUPPORTED_EFFECTS_SCOPE_DOMAIN) ? set : clr); - printf(" NVM Subsystem SCOPE%s", (fsp & NVME_FID_SUPPORTED_EFFECTS_SCOPE_NSS) ? set : clr); } void nvme_show_fid_support_effects_log(struct nvme_fid_supported_effects_log *fid_log, const char *devname, enum nvme_print_flags flags) { - __u32 fid_effect; - int i, human = flags & VERBOSE; - nvme_print(fid_supported_effects_log, flags, fid_log, devname); if (flags & BINARY) return d_raw((unsigned char *)fid_log, sizeof(*fid_log)); - - printf("FID Supports Effects Log for device: %s\n", devname); - printf("Admin Command Set\n"); - for (i = 0; i < 256; i++) { - fid_effect = le32_to_cpu(fid_log->fid_support[i]); - if (fid_effect & NVME_FID_SUPPORTED_EFFECTS_FSUPP) { - printf("FID %02x -> Support Effects Log: %08x", i, - fid_effect); - if (human) - nvme_show_fid_support_effects_log_human(fid_effect); - else - printf("\n"); - } - } -} - -static void nvme_show_mi_cmd_support_effects_log_human(__u32 mi_cmd_support) -{ - const char *set = "+"; - const char *clr = "-"; - __u16 csp; - - printf(" CSUPP+"); - printf(" UDCC%s", (mi_cmd_support & NVME_MI_CMD_SUPPORTED_EFFECTS_UDCC) ? set : clr); - printf(" NCC%s", (mi_cmd_support & NVME_MI_CMD_SUPPORTED_EFFECTS_NCC) ? set : clr); - printf(" NIC%s", (mi_cmd_support & NVME_MI_CMD_SUPPORTED_EFFECTS_NIC) ? set : clr); - printf(" CCC%s", (mi_cmd_support & NVME_MI_CMD_SUPPORTED_EFFECTS_CCC) ? set : clr); - - csp = (mi_cmd_support >> NVME_MI_CMD_SUPPORTED_EFFECTS_SCOPE_SHIFT) & NVME_MI_CMD_SUPPORTED_EFFECTS_SCOPE_MASK; - - printf(" NAMESPACE SCOPE%s", (csp & NVME_MI_CMD_SUPPORTED_EFFECTS_SCOPE_NS) ? set : clr); - printf(" CONTROLLER SCOPE%s", (csp & NVME_MI_CMD_SUPPORTED_EFFECTS_SCOPE_CTRL) ? set : clr); - printf(" NVM SET SCOPE%s", (csp & NVME_MI_CMD_SUPPORTED_EFFECTS_SCOPE_NVM_SET) ? set : clr); - printf(" ENDURANCE GROUP SCOPE%s", (csp & NVME_MI_CMD_SUPPORTED_EFFECTS_SCOPE_ENDGRP) ? set : clr); - printf(" DOMAIN SCOPE%s", (csp & NVME_MI_CMD_SUPPORTED_EFFECTS_SCOPE_DOMAIN) ? set : clr); - printf(" NVM Subsystem SCOPE%s", (csp & NVME_MI_CMD_SUPPORTED_EFFECTS_SCOPE_NSS) ? set : clr); } void nvme_show_mi_cmd_support_effects_log(struct nvme_mi_cmd_supported_effects_log *mi_cmd_log, const char *devname, enum nvme_print_flags flags) { - __u32 mi_cmd_effect; - int i, human = flags & VERBOSE; - nvme_print(mi_cmd_support_effects_log, flags, mi_cmd_log, devname); if (flags & BINARY) return d_raw((unsigned char *)mi_cmd_log, sizeof(*mi_cmd_log)); - - printf("MI Commands Support Effects Log for device: %s\n", devname); - printf("Admin Command Set\n"); - for (i = 0; i < NVME_LOG_MI_CMD_SUPPORTED_EFFECTS_MAX; i++) { - mi_cmd_effect = le32_to_cpu(mi_cmd_log->mi_cmd_support[i]); - if (mi_cmd_effect & NVME_MI_CMD_SUPPORTED_EFFECTS_CSUPP) { - printf("MI CMD %02x -> Support Effects Log: %08x", i, - mi_cmd_effect); - if (human) - nvme_show_mi_cmd_support_effects_log_human(mi_cmd_effect); - else - printf("\n"); - } - } } void nvme_show_boot_part_log(void *bp_log, const char *devname, __u32 size, enum nvme_print_flags flags) { - struct nvme_boot_partition *hdr; - nvme_print(boot_part_log, flags, bp_log, devname, size); if (flags & BINARY) return d_raw((unsigned char *)bp_log, size); - - hdr = bp_log; - printf("Boot Partition Log for device: %s\n", devname); - printf("Log ID: %u\n", hdr->lid); - printf("Boot Partition Size: %u KiB\n", le32_to_cpu(hdr->bpinfo) & 0x7fff); - printf("Active BPID: %u\n", (le32_to_cpu(hdr->bpinfo) >> 31) & 0x1); } void nvme_show_media_unit_stat_log(struct nvme_media_unit_stat_log *mus_log, enum nvme_print_flags flags) { - int i; - int nmu = le16_to_cpu(mus_log->nmu); - nvme_print(media_unit_stat_log, flags, mus_log); if (flags & BINARY) return d_raw((unsigned char *)mus_log, sizeof(*mus_log)); - - printf("Number of Media Unit Status Descriptors: %u\n", nmu); - printf("Number of Channels: %u\n", le16_to_cpu(mus_log->cchans)); - printf("Selected Configuration: %u\n", le16_to_cpu(mus_log->sel_config)); - for (i = 0; i < nmu; i++) { - printf("Media Unit Status Descriptor: %u\n", i); - printf("Media Unit Identifier: %u\n", - le16_to_cpu(mus_log->mus_desc[i].muid)); - printf("Domain Identifier: %u\n", - le16_to_cpu(mus_log->mus_desc[i].domainid)); - printf("Endurance Group Identifier: %u\n", - le16_to_cpu(mus_log->mus_desc[i].endgid)); - printf("NVM Set Identifier: %u\n", - le16_to_cpu(mus_log->mus_desc[i].nvmsetid)); - printf("Capacity Adjustment Factor: %u\n", - le16_to_cpu(mus_log->mus_desc[i].cap_adj_fctr)); - printf("Available Spare: %u\n", mus_log->mus_desc[i].avl_spare); - printf("Percentage Used: %u\n", mus_log->mus_desc[i].percent_used); - printf("Number of Channels: %u\n", mus_log->mus_desc[i].mucs); - printf("Channel Identifiers Offset: %u\n", mus_log->mus_desc[i].cio); - } -} - -void nvme_show_fdp_config_fdpa(uint8_t fdpa) -{ - __u8 valid = (fdpa >> 7) & 0x1; - __u8 rsvd = (fdpa >> 5) >> 0x3; - __u8 fdpvwc = (fdpa >> 4) & 0x1; - __u8 rgif = fdpa & 0xf; - - printf(" [7:7] : %#x\tFDP Configuration %sValid\n", - valid, valid ? "" : "Not "); - if (rsvd) - printf(" [6:5] : %#x\tReserved\n", rsvd); - printf(" [4:4] : %#x\tFDP Volatile Write Cache %sPresent\n", - fdpvwc, fdpvwc ? "" : "Not "); - printf(" [3:0] : %#x\tReclaim Group Identifier Format\n", rgif); } void nvme_show_fdp_configs(struct nvme_fdp_config_log *log, size_t len, enum nvme_print_flags flags) { - void *p = log->configs; - int human = flags & VERBOSE; - uint16_t n; - nvme_print(fdp_config_log, flags, log, len); if (flags & BINARY) return d_raw((unsigned char *)log, len); - - n = le16_to_cpu(log->n) + 1; - - for (int i = 0; i < n; i++) { - struct nvme_fdp_config_desc *config = p; - - printf("FDP Attributes: %#x\n", config->fdpa); - if (human) - nvme_show_fdp_config_fdpa(config->fdpa); - - printf("Vendor Specific Size: %u\n", config->vss); - printf("Number of Reclaim Groups: %"PRIu32"\n", le32_to_cpu(config->nrg)); - printf("Number of Reclaim Unit Handles: %"PRIu16"\n", le16_to_cpu(config->nruh)); - printf("Number of Namespaces Supported: %"PRIu32"\n", le32_to_cpu(config->nnss)); - printf("Reclaim Unit Nominal Size: %"PRIu64"\n", le64_to_cpu(config->runs)); - printf("Estimated Reclaim Unit Time Limit: %"PRIu32"\n", le32_to_cpu(config->erutl)); - - printf("Reclaim Unit Handle List:\n"); - for (int j = 0; j < le16_to_cpu(config->nruh); j++) { - struct nvme_fdp_ruh_desc *ruh = &config->ruhs[j]; - - printf(" [%d]: %s\n", j, ruh->ruht == NVME_FDP_RUHT_INITIALLY_ISOLATED ? "Initially Isolated" : "Persistently Isolated"); - } - - p += config->size; - } } void nvme_show_fdp_usage(struct nvme_fdp_ruhu_log *log, size_t len, @@ -880,17 +310,6 @@ void nvme_show_fdp_usage(struct nvme_fdp_ruhu_log *log, size_t len, if (flags & BINARY) return d_raw((unsigned char *)log, len); - - uint16_t nruh = le16_to_cpu(log->nruh); - - for (int i = 0; i < nruh; i++) { - struct nvme_fdp_ruhu_desc *ruhu = &log->ruhus[i]; - - printf("Reclaim Unit Handle %d Attributes: 0x%"PRIx8" (%s)\n", i, ruhu->ruha, - ruhu->ruha == 0x0 ? "Unused" : ( - ruhu->ruha == 0x1 ? "Host Specified" : ( - ruhu->ruha == 0x2 ? "Controller Specified" : "Unknown"))); - } } void nvme_show_fdp_stats(struct nvme_fdp_stats_log *log, @@ -900,13 +319,6 @@ void nvme_show_fdp_stats(struct nvme_fdp_stats_log *log, if (flags & BINARY) return d_raw((unsigned char*)log, sizeof(*log)); - - printf("Host Bytes with Metadata Written (HBMW): %s\n", - uint128_t_to_l10n_string(le128_to_cpu(log->hbmw))); - printf("Media Bytes with Metadata Written (MBMW): %s\n", - uint128_t_to_l10n_string(le128_to_cpu(log->mbmw))); - printf("Media Bytes Erased (MBE): %s\n", - uint128_t_to_l10n_string(le128_to_cpu(log->mbe))); } const char *nvme_fdp_event_to_string(enum nvme_fdp_event_type event) @@ -926,52 +338,10 @@ const char *nvme_fdp_event_to_string(enum nvme_fdp_event_type event) void nvme_show_fdp_events(struct nvme_fdp_events_log *log, enum nvme_print_flags flags) { - struct tm *tm; - char buffer[320]; - time_t ts; - nvme_print(fdp_event_log, flags, log); if (flags & BINARY) return d_raw((unsigned char*)log, sizeof(*log)); - - uint32_t n = le32_to_cpu(log->n); - - for (unsigned int i = 0; i < n; i++) { - struct nvme_fdp_event *event = &log->events[i]; - - ts = int48_to_long(event->ts.timestamp) / 1000; - tm = localtime(&ts); - - printf("Event[%u]\n", i); - printf(" Event Type: 0x%"PRIx8" (%s)\n", event->type, nvme_fdp_event_to_string(event->type)); - printf(" Event Timestamp: %"PRIu64" (%s)\n", int48_to_long(event->ts.timestamp), - strftime(buffer, sizeof(buffer), "%c %Z", tm) ? buffer : "-"); - - if (event->flags & NVME_FDP_EVENT_F_PIV) - printf(" Placement Identifier (PID): 0x%"PRIx16"\n", le16_to_cpu(event->pid)); - - if (event->flags & NVME_FDP_EVENT_F_NSIDV) - printf(" Namespace Identifier (NSID): %"PRIu32"\n", le32_to_cpu(event->nsid)); - - if (event->type == NVME_FDP_EVENT_REALLOC) { - struct nvme_fdp_event_realloc *mr; - mr = (struct nvme_fdp_event_realloc *)&event->type_specific; - - printf(" Number of LBAs Moved (NLBAM): %"PRIu16"\n", le16_to_cpu(mr->nlbam)); - - if (mr->flags & NVME_FDP_EVENT_REALLOC_F_LBAV) { - printf(" Logical Block Address (LBA): 0x%"PRIx64"\n", le64_to_cpu(mr->lba)); - } - } - - if (event->flags & NVME_FDP_EVENT_F_LV) { - printf(" Reclaim Group Identifier: %"PRIu16"\n", le16_to_cpu(event->rgid)); - printf(" Reclaim Unit Handle Identifier %"PRIu8"\n", event->ruhid); - } - - printf("\n"); - } } void nvme_show_fdp_ruh_status(struct nvme_fdp_ruh_status *status, size_t len, @@ -982,2217 +352,181 @@ void nvme_show_fdp_ruh_status(struct nvme_fdp_ruh_status *status, size_t len, if (flags & BINARY) return d_raw((unsigned char *)status, len); - - uint16_t nruhsd = le16_to_cpu(status->nruhsd); - - for (unsigned int i = 0; i < nruhsd; i++) { - struct nvme_fdp_ruh_status_desc *ruhs = &status->ruhss[i]; - - printf("Placement Identifier %"PRIu16"; Reclaim Unit Handle Identifier %"PRIu16"\n", - le16_to_cpu(ruhs->pid), le16_to_cpu(ruhs->ruhid)); - printf(" Estimated Active Reclaim Unit Time Remaining (EARUTR): %"PRIu32"\n", - le32_to_cpu(ruhs->earutr)); - printf(" Reclaim Unit Available Media Writes (RUAMW): %"PRIu64"\n", - le64_to_cpu(ruhs->ruamw)); - - printf("\n"); - } } void nvme_show_supported_cap_config_log( struct nvme_supported_cap_config_list_log *cap, enum nvme_print_flags flags) { - struct nvme_end_grp_chan_desc *chan_desc; - int i, j, k, l, m, sccn, egcn, egsets, egchans, chmus; - nvme_print(supported_cap_config_list_log, flags, cap); if (flags & BINARY) return d_raw((unsigned char *)cap, sizeof(*cap)); - - sccn = cap->sccn; - printf("Number of Supported Capacity Configurations: %u\n", sccn); - for (i = 0; i < sccn; i++) { - printf("Capacity Configuration Descriptor: %u\n", i); - printf("Capacity Configuration Identifier: %u\n", - le16_to_cpu(cap->cap_config_desc[i].cap_config_id)); - printf("Domain Identifier: %u\n", - le16_to_cpu(cap->cap_config_desc[i].domainid)); - egcn = le16_to_cpu(cap->cap_config_desc[i].egcn); - printf("Number of Endurance Group Configuration Descriptors: %u\n", egcn); - for(j = 0; j < egcn; j++) { - printf("Endurance Group Identifier: %u\n", - le16_to_cpu(cap->cap_config_desc[i].egcd[j].endgid)); - printf("Capacity Adjustment Factor: %u\n", - le16_to_cpu(cap->cap_config_desc[i].egcd[j].cap_adj_factor)); - printf("Total Endurance Group Capacity: %s\n", - uint128_t_to_l10n_string(le128_to_cpu( - cap->cap_config_desc[i].egcd[j].tegcap))); - printf("Spare Endurance Group Capacity: %s\n", - uint128_t_to_l10n_string(le128_to_cpu( - cap->cap_config_desc[i].egcd[j].segcap))); - printf("Endurance Estimate: %s\n", - uint128_t_to_l10n_string(le128_to_cpu( - cap->cap_config_desc[i].egcd[j].end_est))); - egsets = le16_to_cpu(cap->cap_config_desc[i].egcd[j].egsets); - printf("Number of NVM Sets: %u\n", egsets); - for(k = 0; k < egsets; k++) { - printf("NVM Set %d Identifier: %u\n", i, - le16_to_cpu(cap->cap_config_desc[i].egcd[j].nvmsetid[k])); - } - chan_desc = (struct nvme_end_grp_chan_desc *) \ - ((cap->cap_config_desc[i].egcd[j].nvmsetid[0]) * (sizeof(__u16)*egsets)); - egchans = le16_to_cpu(chan_desc->egchans); - printf("Number of Channels: %u\n", egchans); - for(l = 0; l < egchans; l++) { - printf("Channel Identifier: %u\n", - le16_to_cpu(chan_desc->chan_config_desc[l].chanid)); - chmus = le16_to_cpu(chan_desc->chan_config_desc[l].chmus); - printf("Number of Channel Media Units: %u\n", chmus); - for(m = 0; m < chmus; m++) { - printf("Media Unit Identifier: %u\n", - le16_to_cpu(chan_desc->chan_config_desc[l].mu_config_desc[m].muid)); - printf("Media Unit Descriptor Length: %u\n", - le16_to_cpu(chan_desc->chan_config_desc[l].mu_config_desc[m].mudl)); - } - } - } - } } -static unsigned int nvme_show_subsystem_multipath(nvme_subsystem_t s, - bool show_ana) +void nvme_show_subsystem_list(nvme_root_t r, bool show_ana, + enum nvme_print_flags flags) { - nvme_ns_t n; - nvme_path_t p; - unsigned int i = 0; - - n = nvme_subsystem_first_ns(s); - if (!n) - return 0; - - nvme_namespace_for_each_path(n, p) { - nvme_ctrl_t c = nvme_path_get_ctrl(p); - const char *ana_state = ""; - - if (show_ana) - ana_state = nvme_path_get_ana_state(p); - - printf(" +- %s %s %s %s %s\n", - nvme_ctrl_get_name(c), - nvme_ctrl_get_transport(c), - nvme_ctrl_get_address(c), - nvme_ctrl_get_state(c), - ana_state); - i++; - } - - return i; + nvme_print(print_nvme_subsystem_list, flags, r, show_ana); } -static void nvme_show_subsystem_ctrls(nvme_subsystem_t s) +const char *nvme_register_szu_to_string(__u8 szu) { - nvme_ctrl_t c; - - nvme_subsystem_for_each_ctrl(s, c) { - printf(" +- %s %s %s %s\n", - nvme_ctrl_get_name(c), - nvme_ctrl_get_transport(c), - nvme_ctrl_get_address(c), - nvme_ctrl_get_state(c)); + switch (szu) { + case 0: return "4 KB"; + case 1: return "64 KB"; + case 2: return "1 MB"; + case 3: return "16 MB"; + case 4: return "256 MB"; + case 5: return "4 GB"; + case 6: return "64 GB"; + default:return "Reserved"; } } -static void nvme_show_subsystem(nvme_root_t r, bool show_ana) +const char *nvme_register_pmr_hsts_to_string(__u8 hsts) { - nvme_host_t h; - - nvme_for_each_host(r, h) { - nvme_subsystem_t s; - - nvme_for_each_subsystem(h, s) { - printf("%s - NQN=%s\n", nvme_subsystem_get_name(s), - nvme_subsystem_get_nqn(s)); - printf("\\\n"); - - if (!nvme_show_subsystem_multipath(s, show_ana)) - nvme_show_subsystem_ctrls(s); - } + switch (hsts) { + case 0: return "Normal Operation"; + case 1: return "Restore Error"; + case 2: return "Read Only"; + case 3: return "Unreliable"; + default: return "Reserved"; } } -void nvme_show_subsystem_list(nvme_root_t r, bool show_ana, - enum nvme_print_flags flags) +const char *nvme_register_pmr_pmrszu_to_string(__u8 pmrszu) { - nvme_print(print_nvme_subsystem_list, flags, r, show_ana); - - nvme_show_subsystem(r, show_ana); + switch (pmrszu) { + case 0: return "Bytes"; + case 1: return "One KB"; + case 2: return "One MB"; + case 3: return "One GB"; + default: return "Reserved"; + } } -static void nvme_show_registers_cap(struct nvme_bar_cap *cap) +void nvme_show_ctrl_registers(void *bar, bool fabrics, enum nvme_print_flags flags) { - printf("\tController Ready With Media Support (CRWMS): %s\n", - ((cap->rsvd_crms_nsss_cmbs_pmrs & 0x08) >> 3) ? "Supported" : "Not Supported"); - printf("\tController Ready Independent of Media Support (CRIMS): %s\n", - ((cap->rsvd_crms_nsss_cmbs_pmrs & 0x10) >> 4) ? "Supported" : "Not Supported"); - printf("\tController Memory Buffer Supported (CMBS): The Controller Memory Buffer is %s\n", - ((cap->rsvd_crms_nsss_cmbs_pmrs & 0x02) >> 1) ? "Supported" : - "Not Supported"); - printf("\tPersistent Memory Region Supported (PMRS): The Persistent Memory Region is %s\n", - (cap->rsvd_crms_nsss_cmbs_pmrs & 0x01) ? "Supported" : "Not Supported"); - printf("\tMemory Page Size Maximum (MPSMAX): %u bytes\n", - 1 << (12 + ((cap->mpsmax_mpsmin & 0xf0) >> 4))); - printf("\tMemory Page Size Minimum (MPSMIN): %u bytes\n", - 1 << (12 + (cap->mpsmax_mpsmin & 0x0f))); - printf("\tBoot Partition Support (BPS): %s\n", - (cap->bps_css_nssrs_dstrd & 0x2000) ? "Yes":"No"); - printf("\tCommand Sets Supported (CSS): NVM command set is %s\n", - (cap->bps_css_nssrs_dstrd & 0x0020) ? "Supported" : "Not Supported"); - printf("\t One or more I/O Command Sets are %s\n", - (cap->bps_css_nssrs_dstrd & 0x0800) ? "Supported" : "Not Supported"); - printf("\t %s\n", - (cap->bps_css_nssrs_dstrd & 0x1000) ? "Only Admin Command Set Supported" : - "I/O Command Set is Supported"); - printf("\tNVM Subsystem Reset Supported (NSSRS): %s\n", - (cap->bps_css_nssrs_dstrd & 0x0010) ? "Yes":"No"); - printf("\tDoorbell Stride (DSTRD): %u bytes\n", - 1 << (2 + (cap->bps_css_nssrs_dstrd & 0x000f))); - printf("\tTimeout (TO): %u ms\n", - cap->to * 500); - printf("\tArbitration Mechanism Supported (AMS): Weighted Round Robin with Urgent Priority Class is %s\n", - (cap->ams_cqr & 0x02) ? "supported":"not supported"); - printf("\tContiguous Queues Required (CQR): %s\n", - (cap->ams_cqr & 0x01) ? "Yes":"No"); - printf("\tMaximum Queue Entries Supported (MQES): %u\n\n", - cap->mqes + 1); -} + const unsigned int reg_size = 0x0e1c; /* 0x0000 to 0x0e1b */ -static void nvme_show_registers_version(__u32 vs) -{ - printf("\tNVMe specification %d.%d\n\n", (vs & 0xffff0000) >> 16, - (vs & 0x0000ff00) >> 8); -} + nvme_print(ctrl_registers, flags, bar, fabrics); -static void nvme_show_registers_cc_ams (__u8 ams) -{ - printf("\tArbitration Mechanism Selected (AMS): "); - switch (ams) { - case 0: - printf("Round Robin\n"); - break; - case 1: - printf("Weighted Round Robin with Urgent Priority Class\n"); - break; - case 7: - printf("Vendor Specific\n"); - break; - default: - printf("Reserved\n"); - } -} + if (flags & BINARY) + return d_raw((unsigned char *)bar, reg_size); -static void nvme_show_registers_cc_shn (__u8 shn) -{ - printf("\tShutdown Notification (SHN): "); - switch (shn) { - case 0: - printf("No notification; no effect\n"); - break; - case 1: - printf("Normal shutdown notification\n"); - break; - case 2: - printf("Abrupt shutdown notification\n"); - break; - default: - printf("Reserved\n"); - } } -static void nvme_show_registers_cc(__u32 cc) +void nvme_show_single_property(int offset, uint64_t value64, enum nvme_print_flags flags) { - printf("\tController Ready Independent of Media Enable (CRIME): %s\n", - NVME_CC_CRIME(cc) ? "Enabled":"Disabled"); - - printf("\tI/O Completion Queue Entry Size (IOCQES): %u bytes\n", - 1 << ((cc & 0x00f00000) >> NVME_CC_IOCQES_SHIFT)); - printf("\tI/O Submission Queue Entry Size (IOSQES): %u bytes\n", - 1 << ((cc & 0x000f0000) >> NVME_CC_IOSQES_SHIFT)); - nvme_show_registers_cc_shn((cc & 0x0000c000) >> NVME_CC_SHN_SHIFT); - nvme_show_registers_cc_ams((cc & 0x00003800) >> NVME_CC_AMS_SHIFT); - printf("\tMemory Page Size (MPS): %u bytes\n", - 1 << (12 + ((cc & 0x00000780) >> NVME_CC_MPS_SHIFT))); - printf("\tI/O Command Set Selected (CSS): %s\n", - (cc & 0x00000070) == 0x00 ? "NVM Command Set" : - (cc & 0x00000070) == 0x60 ? "All supported I/O Command Sets" : - (cc & 0x00000070) == 0x70 ? "Admin Command Set only" : "Reserved"); - printf("\tEnable (EN): %s\n\n", - (cc & 0x00000001) ? "Yes":"No"); + nvme_print(single_property, flags, offset, value64); } -static void nvme_show_registers_csts_shst(__u8 shst) +void nvme_show_relatives(const char *name) { - printf("\tShutdown Status (SHST): "); - switch (shst) { - case 0: - printf("Normal operation (no shutdown has been requested)\n"); - break; - case 1: - printf("Shutdown processing occurring\n"); - break; - case 2: - printf("Shutdown processing complete\n"); - break; - default: - printf("Reserved\n"); - } + /* XXX: TBD */ } -static void nvme_show_registers_csts(__u32 csts) +void d(unsigned char *buf, int len, int width, int group) { - printf("\tProcessing Paused (PP): %s\n", - (csts & 0x00000020) ? "Yes":"No"); - printf("\tNVM Subsystem Reset Occurred (NSSRO): %s\n", - (csts & 0x00000010) ? "Yes":"No"); - nvme_show_registers_csts_shst((csts & 0x0000000c) >> 2); - printf("\tController Fatal Status (CFS): %s\n", - (csts & 0x00000002) ? "True":"False"); - printf("\tReady (RDY): %s\n\n", - (csts & 0x00000001) ? "Yes":"No"); + int i, offset = 0, line_done = 0; + char ascii[32 + 1]; + assert(width < sizeof(ascii)); + printf(" "); + for (i = 0; i <= 15; i++) + printf("%3x", i); + for (i = 0; i < len; i++) { + line_done = 0; + if (i % width == 0) + printf( "\n%04x:", offset); + if (i % group == 0) + printf( " %02x", buf[i]); + else + printf( "%02x", buf[i]); + ascii[i % width] = (buf[i] >= '!' && buf[i] <= '~') ? buf[i] : '.'; + if (((i + 1) % width) == 0) { + ascii[i % width + 1] = '\0'; + printf( " \"%.*s\"", width, ascii); + offset += width; + line_done = 1; + } + } + if (!line_done) { + unsigned b = width - (i % width); + ascii[i % width + 1] = '\0'; + printf( " %*s \"%.*s\"", + 2 * b + b / group + (b % group ? 1 : 0), "", + width, ascii); + } + printf( "\n"); } -static void nvme_show_registers_crto(__u32 crto) +void d_raw(unsigned char *buf, unsigned len) { - printf("\tCRIMT : %d secs\n", - NVME_CRTO_CRIMT(crto)/2 ); - printf("\tCRWMT : %d secs\n", - NVME_CRTO_CRWMT(crto)/2 ); + unsigned i; + for (i = 0; i < len; i++) + putchar(*(buf+i)); } -static void nvme_show_registers_aqa(__u32 aqa) +void nvme_show_status(int status) { - printf("\tAdmin Completion Queue Size (ACQS): %u\n", - ((aqa & 0x0fff0000) >> 16) + 1); - printf("\tAdmin Submission Queue Size (ASQS): %u\n\n", - (aqa & 0x00000fff) + 1); - -} + struct print_ops *ops; -static void nvme_show_registers_cmbloc(__u32 cmbloc, __u32 cmbsz) -{ - static const char *enforced[] = { "Enforced", "Not Enforced" }; + if (argconfig_output_format_json(false)) + ops = nvme_print_ops(JSON); + else + ops =nvme_print_ops(0); - if (cmbsz == 0) { - printf("\tController Memory Buffer feature is not supported\n\n"); + if (!ops) return; - } - printf("\tOffset (OFST): 0x%x (See cmbsz.szu for granularity)\n", - (cmbloc & 0xfffff000) >> 12); - - printf("\tCMB Queue Dword Alignment (CQDA): %d\n", - (cmbloc & 0x00000100) >> 8); - - printf("\tCMB Data Metadata Mixed Memory Support (CDMMMS): %s\n", - enforced[(cmbloc & 0x00000080) >> 7]); - - printf("\tCMB Data Pointer and Command Independent Locations Support (CDPCILS): %s\n", - enforced[(cmbloc & 0x00000040) >> 6]); - - printf("\tCMB Data Pointer Mixed Locations Support (CDPMLS): %s\n", - enforced[(cmbloc & 0x00000020) >> 5]); - - printf("\tCMB Queue Physically Discontiguous Support (CQPDS): %s\n", - enforced[(cmbloc & 0x00000010) >> 4]); - printf("\tCMB Queue Mixed Memory Support (CQMMS): %s\n", - enforced[(cmbloc & 0x00000008) >> 3]); + if (!ops->show_status) + return; - printf("\tBase Indicator Register (BIR): 0x%x\n\n", - (cmbloc & 0x00000007)); + ops->show_status(status); } -const char *nvme_register_szu_to_string(__u8 szu) +void nvme_show_id_ctrl_rpmbs(__le32 ctrl_rpmbs, enum nvme_print_flags flags) { - switch (szu) { - case 0: return "4 KB"; - case 1: return "64 KB"; - case 2: return "1 MB"; - case 3: return "16 MB"; - case 4: return "256 MB"; - case 5: return "4 GB"; - case 6: return "64 GB"; - default:return "Reserved"; - } + nvme_print(id_ctrl_rpmbs, flags, ctrl_rpmbs); } -static void nvme_show_registers_cmbsz(__u32 cmbsz) +void nvme_show_id_ns(struct nvme_id_ns *ns, unsigned int nsid, + unsigned int lba_index, bool cap_only, enum nvme_print_flags flags) { - if (cmbsz == 0) { - printf("\tController Memory Buffer feature is not supported\n\n"); - return; - } - printf("\tSize (SZ): %u\n", - (cmbsz & 0xfffff000) >> 12); - printf("\tSize Units (SZU): %s\n", - nvme_register_szu_to_string((cmbsz & 0x00000f00) >> 8)); - printf("\tWrite Data Support (WDS): Write Data and metadata transfer in Controller Memory Buffer is %s\n", - (cmbsz & 0x00000010) ? "Supported":"Not supported"); - printf("\tRead Data Support (RDS): Read Data and metadata transfer in Controller Memory Buffer is %s\n", - (cmbsz & 0x00000008) ? "Supported":"Not supported"); - printf("\tPRP SGL List Support (LISTS): PRP/SG Lists in Controller Memory Buffer is %s\n", - (cmbsz & 0x00000004) ? "Supported":"Not supported"); - printf("\tCompletion Queue Support (CQS): Admin and I/O Completion Queues in Controller Memory Buffer is %s\n", - (cmbsz & 0x00000002) ? "Supported":"Not supported"); - printf("\tSubmission Queue Support (SQS): Admin and I/O Submission Queues in Controller Memory Buffer is %s\n\n", - (cmbsz & 0x00000001) ? "Supported":"Not supported"); -} + nvme_print(id_ns, flags, ns, nsid, lba_index, cap_only); -static void nvme_show_registers_bpinfo_brs(__u8 brs) -{ - printf("\tBoot Read Status (BRS): "); - switch (brs) { - case 0: - printf("No Boot Partition read operation requested\n"); - break; - case 1: - printf("Boot Partition read in progress\n"); - break; - case 2: - printf("Boot Partition read completed successfully\n"); - break; - case 3: - printf("Error completing Boot Partition read\n"); - break; - default: - printf("Invalid\n"); - } + if (flags & BINARY) + return d_raw((unsigned char *)ns, sizeof(*ns)); } -static void nvme_show_registers_bpinfo(__u32 bpinfo) -{ - printf("\tActive Boot Partition ID (ABPID): %u\n", - (bpinfo & 0x80000000) >> 31); - nvme_show_registers_bpinfo_brs((bpinfo & 0x03000000) >> 24); - printf("\tBoot Partition Size (BPSZ): %u\n", - bpinfo & 0x00007fff); -} -static void nvme_show_registers_bprsel(__u32 bprsel) +void nvme_show_cmd_set_independent_id_ns( + struct nvme_id_independent_id_ns *ns, unsigned int nsid, + enum nvme_print_flags flags) { - printf("\tBoot Partition Identifier (BPID): %u\n", - (bprsel & 0x80000000) >> 31); - printf("\tBoot Partition Read Offset (BPROF): %x\n", - (bprsel & 0x3ffffc00) >> 10); - printf("\tBoot Partition Read Size (BPRSZ): %x\n", - bprsel & 0x000003ff); + nvme_print(id_independent_id_ns, flags, ns, nsid); + + if (flags & BINARY) + return d_raw((unsigned char *)ns, sizeof(*ns)); } -static void nvme_show_registers_bpmbl(uint64_t bpmbl) +void nvme_show_id_ns_descs(void *data, unsigned nsid, enum nvme_print_flags flags) { + nvme_print(id_ns_descs, flags, data, nsid); - printf("\tBoot Partition Memory Buffer Base Address (BMBBA): %"PRIx64"\n", - bpmbl); + if (flags & BINARY) + return d_raw((unsigned char *)data, 0x1000); } -static void nvme_show_registers_cmbmsc(uint64_t cmbmsc) +void nvme_show_id_ctrl(struct nvme_id_ctrl *ctrl, enum nvme_print_flags flags, + void (*vendor_show)(__u8 *vs, struct json_object *root)) { - printf("\tController Base Address (CBA): %" PRIx64 "\n", - (cmbmsc & 0xfffffffffffff000) >> 12); - printf("\tController Memory Space Enable (CMSE): %" PRIx64 "\n", - (cmbmsc & 0x0000000000000002) >> 1); - printf("\tCapabilities Registers Enabled (CRE): CMBLOC and "\ - "CMBSZ registers are%senabled\n\n", - (cmbmsc & 0x0000000000000001) ? " " : " NOT "); -} + nvme_print(id_ctrl, flags, ctrl, vendor_show); -static void nvme_show_registers_cmbsts(__u32 cmbsts) -{ - printf("\tController Base Address Invalid (CBAI): %x\n\n", - (cmbsts & 0x00000001)); -} - -static void nvme_show_registers_pmrcap(__u32 pmrcap) -{ - printf("\tController Memory Space Supported (CMSS): "\ - "Referencing PMR with host supplied addresses is %s\n", - ((pmrcap & 0x01000000) >> 24) ? "Supported" : "Not Supported"); - printf("\tPersistent Memory Region Timeout (PMRTO): %x\n", - (pmrcap & 0x00ff0000) >> 16); - printf("\tPersistent Memory Region Write Barrier Mechanisms (PMRWBM): %x\n", - (pmrcap & 0x00003c00) >> 10); - printf("\tPersistent Memory Region Time Units (PMRTU): PMR time unit is %s\n", - (pmrcap & 0x00000300) >> 8 ? "minutes":"500 milliseconds"); - printf("\tBase Indicator Register (BIR): %x\n", - (pmrcap & 0x000000e0) >> 5); - printf("\tWrite Data Support (WDS): Write data to the PMR is %s\n", - (pmrcap & 0x00000010) ? "supported":"not supported"); - printf("\tRead Data Support (RDS): Read data from the PMR is %s\n", - (pmrcap & 0x00000008) ? "supported":"not supported"); -} - -static void nvme_show_registers_pmrctl(__u32 pmrctl) -{ - printf("\tEnable (EN): PMR is %s\n", (pmrctl & 0x00000001) ? - "READY" : "Disabled"); -} - -const char *nvme_register_pmr_hsts_to_string(__u8 hsts) -{ - switch (hsts) { - case 0: return "Normal Operation"; - case 1: return "Restore Error"; - case 2: return "Read Only"; - case 3: return "Unreliable"; - default: return "Reserved"; - } -} - -static void nvme_show_registers_pmrsts(__u32 pmrsts, __u32 pmrctl) -{ - printf("\tController Base Address Invalid (CBAI): %x\n", - (pmrsts & 0x00001000) >> 12); - printf("\tHealth Status (HSTS): %s\n", - nvme_register_pmr_hsts_to_string((pmrsts & 0x00000e00) >> 9)); - printf("\tNot Ready (NRDY): "\ - "The Persistent Memory Region is %s to process "\ - "PCI Express memory read and write requests\n", - (pmrsts & 0x00000100) == 0 && (pmrctl & 0x00000001) ? - "READY":"Not Ready"); - printf("\tError (ERR): %x\n", (pmrsts & 0x000000ff)); -} - -const char *nvme_register_pmr_pmrszu_to_string(__u8 pmrszu) -{ - switch (pmrszu) { - case 0: return "Bytes"; - case 1: return "One KB"; - case 2: return "One MB"; - case 3: return "One GB"; - default: return "Reserved"; - } -} - -static void nvme_show_registers_pmrebs(__u32 pmrebs) -{ - printf("\tPMR Elasticity Buffer Size Base (PMRWBZ): %x\n", (pmrebs & 0xffffff00) >> 8); - printf("\tRead Bypass Behavior : memory reads not conflicting with memory writes "\ - "in the PMR Elasticity Buffer %s bypass those memory writes\n", - (pmrebs & 0x00000010) ? "SHALL":"MAY"); - printf("\tPMR Elasticity Buffer Size Units (PMRSZU): %s\n", - nvme_register_pmr_pmrszu_to_string(pmrebs & 0x0000000f)); -} - -static void nvme_show_registers_pmrswtp(__u32 pmrswtp) -{ - printf("\tPMR Sustained Write Throughput (PMRSWTV): %x\n", - (pmrswtp & 0xffffff00) >> 8); - printf("\tPMR Sustained Write Throughput Units (PMRSWTU): %s/second\n", - nvme_register_pmr_pmrszu_to_string(pmrswtp & 0x0000000f)); -} - -static void nvme_show_registers_pmrmscl(uint32_t pmrmscl) -{ - printf("\tController Base Address (CBA): %#x\n", - (pmrmscl & 0xfffff000) >> 12); - printf("\tController Memory Space Enable (CMSE): %#x\n\n", - (pmrmscl & 0x00000002) >> 1); -} - -static void nvme_show_registers_pmrmscu(uint32_t pmrmscu) -{ - printf("\tController Base Address (CBA): %#x\n", - pmrmscu); -} - -void nvme_show_ctrl_registers(void *bar, bool fabrics, enum nvme_print_flags flags) -{ - const unsigned int reg_size = 0x0e1c; /* 0x0000 to 0x0e1b */ - uint64_t cap, asq, acq, bpmbl, cmbmsc; - uint32_t vs, intms, intmc, cc, csts, nssr, crto, aqa, cmbsz, cmbloc, bpinfo, - bprsel, cmbsts, pmrcap, pmrctl, pmrsts, pmrebs, pmrswtp, - pmrmscl, pmrmscu; - int human = flags & VERBOSE; - - nvme_print(ctrl_registers, flags, bar, fabrics); - - if (flags & BINARY) - return d_raw((unsigned char *)bar, reg_size); - - cap = mmio_read64(bar + NVME_REG_CAP); - vs = mmio_read32(bar + NVME_REG_VS); - intms = mmio_read32(bar + NVME_REG_INTMS); - intmc = mmio_read32(bar + NVME_REG_INTMC); - cc = mmio_read32(bar + NVME_REG_CC); - csts = mmio_read32(bar + NVME_REG_CSTS); - nssr = mmio_read32(bar + NVME_REG_NSSR); - crto = mmio_read32(bar + NVME_REG_CRTO); - aqa = mmio_read32(bar + NVME_REG_AQA); - asq = mmio_read64(bar + NVME_REG_ASQ); - acq = mmio_read64(bar + NVME_REG_ACQ); - cmbloc = mmio_read32(bar + NVME_REG_CMBLOC); - cmbsz = mmio_read32(bar + NVME_REG_CMBSZ); - bpinfo = mmio_read32(bar + NVME_REG_BPINFO); - bprsel = mmio_read32(bar + NVME_REG_BPRSEL); - bpmbl = mmio_read64(bar + NVME_REG_BPMBL); - cmbmsc = mmio_read64(bar + NVME_REG_CMBMSC); - cmbsts = mmio_read32(bar + NVME_REG_CMBSTS); - pmrcap = mmio_read32(bar + NVME_REG_PMRCAP); - pmrctl = mmio_read32(bar + NVME_REG_PMRCTL); - pmrsts = mmio_read32(bar + NVME_REG_PMRSTS); - pmrebs = mmio_read32(bar + NVME_REG_PMREBS); - pmrswtp = mmio_read32(bar + NVME_REG_PMRSWTP); - pmrmscl = mmio_read32(bar + NVME_REG_PMRMSCL); - pmrmscu = mmio_read32(bar + NVME_REG_PMRMSCU); - - if (human) { - if (cap != 0xffffffff) { - printf("cap : %"PRIx64"\n", cap); - nvme_show_registers_cap((struct nvme_bar_cap *)&cap); - } - if (vs != 0xffffffff) { - printf("version : %x\n", vs); - nvme_show_registers_version(vs); - } - if (cc != 0xffffffff) { - printf("cc : %x\n", cc); - nvme_show_registers_cc(cc); - } - if (csts != 0xffffffff) { - printf("csts : %x\n", csts); - nvme_show_registers_csts(csts); - } - if (nssr != 0xffffffff) { - printf("nssr : %x\n", nssr); - printf("\tNVM Subsystem Reset Control (NSSRC): %u\n\n", - nssr); - } - if (crto != 0xffffffff) { - printf("crto : %x\n", crto); - nvme_show_registers_crto(crto); - } - if (!fabrics) { - printf("intms : %x\n", intms); - printf("\tInterrupt Vector Mask Set (IVMS): %x\n\n", - intms); - - printf("intmc : %x\n", intmc); - printf("\tInterrupt Vector Mask Clear (IVMC): %x\n\n", - intmc); - printf("aqa : %x\n", aqa); - nvme_show_registers_aqa(aqa); - - printf("asq : %"PRIx64"\n", asq); - printf("\tAdmin Submission Queue Base (ASQB): %"PRIx64"\n\n", - asq); - - printf("acq : %"PRIx64"\n", acq); - printf("\tAdmin Completion Queue Base (ACQB): %"PRIx64"\n\n", - acq); - - printf("cmbloc : %x\n", cmbloc); - nvme_show_registers_cmbloc(cmbloc, cmbsz); - - printf("cmbsz : %x\n", cmbsz); - nvme_show_registers_cmbsz(cmbsz); - - printf("bpinfo : %x\n", bpinfo); - nvme_show_registers_bpinfo(bpinfo); - - printf("bprsel : %x\n", bprsel); - nvme_show_registers_bprsel(bprsel); - - printf("bpmbl : %"PRIx64"\n", bpmbl); - nvme_show_registers_bpmbl(bpmbl); - - printf("cmbmsc : %"PRIx64"\n", cmbmsc); - nvme_show_registers_cmbmsc(cmbmsc); - - printf("cmbsts : %x\n", cmbsts); - nvme_show_registers_cmbsts(cmbsts); - - printf("pmrcap : %x\n", pmrcap); - nvme_show_registers_pmrcap(pmrcap); - - printf("pmrctl : %x\n", pmrctl); - nvme_show_registers_pmrctl(pmrctl); - - printf("pmrsts : %x\n", pmrsts); - nvme_show_registers_pmrsts(pmrsts, pmrctl); - - printf("pmrebs : %x\n", pmrebs); - nvme_show_registers_pmrebs(pmrebs); - - printf("pmrswtp : %x\n", pmrswtp); - nvme_show_registers_pmrswtp(pmrswtp); - - printf("pmrmscl : %#x\n", pmrmscl); - nvme_show_registers_pmrmscl(pmrmscl); - - printf("pmrmscu : %#x\n", pmrmscu); - nvme_show_registers_pmrmscu(pmrmscu); - } - } else { - if (cap != 0xffffffff) - printf("cap : %"PRIx64"\n", cap); - if (vs != 0xffffffff) - printf("version : %x\n", vs); - if (cc != 0xffffffff) - printf("cc : %x\n", cc); - if (csts != 0xffffffff) - printf("csts : %x\n", csts); - if (nssr != 0xffffffff) - printf("nssr : %x\n", nssr); - if (crto != 0xffffffff) - printf("crto : %x\n", crto); - if (!fabrics) { - printf("intms : %x\n", intms); - printf("intmc : %x\n", intmc); - printf("aqa : %x\n", aqa); - printf("asq : %"PRIx64"\n", asq); - printf("acq : %"PRIx64"\n", acq); - printf("cmbloc : %x\n", cmbloc); - printf("cmbsz : %x\n", cmbsz); - printf("bpinfo : %x\n", bpinfo); - printf("bprsel : %x\n", bprsel); - printf("bpmbl : %"PRIx64"\n", bpmbl); - printf("cmbmsc : %"PRIx64"\n", cmbmsc); - printf("cmbsts : %x\n", cmbsts); - printf("pmrcap : %x\n", pmrcap); - printf("pmrctl : %x\n", pmrctl); - printf("pmrsts : %x\n", pmrsts); - printf("pmrebs : %x\n", pmrebs); - printf("pmrswtp : %x\n", pmrswtp); - printf("pmrmscl : %#x\n", pmrmscl); - printf("pmrmscu : %#x\n", pmrmscu); - } - } -} - -void nvme_show_single_property(int offset, uint64_t value64, enum nvme_print_flags flags) -{ - uint32_t value32; - int human = flags & VERBOSE; - - nvme_print(single_property, flags, offset, value64); - - if (!human) { - if (nvme_is_64bit_reg(offset)) - printf("property: 0x%02x (%s), value: %"PRIx64"\n", - offset, nvme_register_to_string(offset), - value64); - else - printf("property: 0x%02x (%s), value: %x\n", offset, - nvme_register_to_string(offset), - (uint32_t) value64); - - return; - } - - value32 = (uint32_t) value64; - - switch (offset) { - case NVME_REG_CAP: - printf("cap : %"PRIx64"\n", value64); - nvme_show_registers_cap((struct nvme_bar_cap *)&value64); - break; - - case NVME_REG_VS: - printf("version : %x\n", value32); - nvme_show_registers_version(value32); - break; - - case NVME_REG_CC: - printf("cc : %x\n", value32); - nvme_show_registers_cc(value32); - break; - - case NVME_REG_CSTS: - printf("csts : %x\n", value32); - nvme_show_registers_csts(value32); - break; - - case NVME_REG_NSSR: - printf("nssr : %x\n", value32); - printf("\tNVM Subsystem Reset Control (NSSRC): %u\n\n", - value32); - break; - - case NVME_REG_CRTO: - printf("crto : %x\n", value32); - nvme_show_registers_crto(value32); - break; - - default: - printf("unknown property: 0x%02x (%s), value: %"PRIx64"\n", - offset, nvme_register_to_string(offset), value64); - break; - } -} - -void nvme_show_relatives(const char *name) -{ - /* XXX: TBD */ -} - -void d(unsigned char *buf, int len, int width, int group) -{ - int i, offset = 0, line_done = 0; - char ascii[32 + 1]; - - assert(width < sizeof(ascii)); - printf(" "); - for (i = 0; i <= 15; i++) - printf("%3x", i); - for (i = 0; i < len; i++) { - line_done = 0; - if (i % width == 0) - printf( "\n%04x:", offset); - if (i % group == 0) - printf( " %02x", buf[i]); - else - printf( "%02x", buf[i]); - ascii[i % width] = (buf[i] >= '!' && buf[i] <= '~') ? buf[i] : '.'; - if (((i + 1) % width) == 0) { - ascii[i % width + 1] = '\0'; - printf( " \"%.*s\"", width, ascii); - offset += width; - line_done = 1; - } - } - if (!line_done) { - unsigned b = width - (i % width); - ascii[i % width + 1] = '\0'; - printf( " %*s \"%.*s\"", - 2 * b + b / group + (b % group ? 1 : 0), "", - width, ascii); - } - printf( "\n"); -} - -void d_raw(unsigned char *buf, unsigned len) -{ - unsigned i; - for (i = 0; i < len; i++) - putchar(*(buf+i)); -} - -void nvme_show_status(int status) -{ - struct print_ops *ops; - int val; - int type; - - if (argconfig_output_format_json(false)) { - ops = nvme_print_ops(JSON); - if (!ops) - return; - - if (!ops->show_status) - return; - ops->show_status(status); - return; - } - - /* - * Callers should be checking for negative values first, but provide a - * sensible fallback anyway - */ - if (status < 0) { - fprintf(stderr, "Error: %s\n", nvme_strerror(errno)); - return; - } - - val = nvme_status_get_value(status); - type = nvme_status_get_type(status); - - switch (type) { - case NVME_STATUS_TYPE_NVME: - fprintf(stderr, "NVMe status: %s(%#x)\n", - nvme_status_to_string(val, false), val); - break; - case NVME_STATUS_TYPE_MI: - fprintf(stderr, "NVMe-MI status: %s(%#x)\n", - nvme_mi_status_to_string(val), val); - break; - default: - fprintf(stderr, "Unknown status type %d, value %#x\n", type, - val); - break; - } -} - -static void nvme_show_id_ctrl_cmic(__u8 cmic) -{ - __u8 rsvd = (cmic & 0xF0) >> 4; - __u8 ana = (cmic & 0x8) >> 3; - __u8 sriov = (cmic & 0x4) >> 2; - __u8 mctl = (cmic & 0x2) >> 1; - __u8 mp = cmic & 0x1; - - if (rsvd) - printf(" [7:4] : %#x\tReserved\n", rsvd); - printf(" [3:3] : %#x\tANA %ssupported\n", ana, ana ? "" : "not "); - printf(" [2:2] : %#x\t%s\n", sriov, sriov ? "SR-IOV" : "PCI"); - printf(" [1:1] : %#x\t%s Controller\n", - mctl, mctl ? "Multi" : "Single"); - printf(" [0:0] : %#x\t%s Port\n", mp, mp ? "Multi" : "Single"); - printf("\n"); -} - -static void nvme_show_id_ctrl_oaes(__le32 ctrl_oaes) -{ - __u32 oaes = le32_to_cpu(ctrl_oaes); - __u32 disc = (oaes >> 31) & 0x1; - __u32 rsvd0 = (oaes & 0x70000000) >> 28; - __u32 zicn = (oaes & 0x08000000) >> 27; - __u32 rsvd1 = (oaes & 0x07FF0000) >> 16; - __u32 normal_shn = (oaes >> 15) & 0x1; - __u32 egealpcn = (oaes & 0x4000) >> 14; - __u32 lbasin = (oaes & 0x2000) >> 13; - __u32 plealcn = (oaes & 0x1000) >> 12; - __u32 anacn = (oaes & 0x800) >> 11; - __u32 rsvd2 = (oaes >> 10) & 0x1; - __u32 fan = (oaes & 0x200) >> 9; - __u32 nace = (oaes & 0x100) >> 8; - __u32 rsvd3 = oaes & 0xFF; - - printf(" [31:31] : %#x\tDiscovery Log Change Notice %sSupported\n", - disc, disc ? "" : "Not "); - if (rsvd0) - printf(" [30:28] : %#x\tReserved\n", rsvd0); - printf(" [27:27] : %#x\tZone Descriptor Changed Notices %sSupported\n", - zicn, zicn ? "" : "Not "); - if (rsvd1) - printf(" [26:16] : %#x\tReserved\n", rsvd1); - printf(" [15:15] : %#x\tNormal NSS Shutdown Event %sSupported\n", - normal_shn, normal_shn ? "" : "Not "); - printf(" [14:14] : %#x\tEndurance Group Event Aggregate Log Page"\ - " Change Notice %sSupported\n", - egealpcn, egealpcn ? "" : "Not "); - printf(" [13:13] : %#x\tLBA Status Information Notices %sSupported\n", - lbasin, lbasin ? "" : "Not "); - printf(" [12:12] : %#x\tPredictable Latency Event Aggregate Log Change"\ - " Notices %sSupported\n", - plealcn, plealcn ? "" : "Not "); - printf(" [11:11] : %#x\tAsymmetric Namespace Access Change Notices"\ - " %sSupported\n", anacn, anacn ? "" : "Not "); - if (rsvd2) - printf(" [10:10] : %#x\tReserved\n", rsvd2); - printf(" [9:9] : %#x\tFirmware Activation Notices %sSupported\n", - fan, fan ? "" : "Not "); - printf(" [8:8] : %#x\tNamespace Attribute Changed Event %sSupported\n", - nace, nace ? "" : "Not "); - if (rsvd3) - printf(" [7:0] : %#x\tReserved\n", rsvd3); - printf("\n"); -} - -static void nvme_show_id_ctrl_ctratt(__le32 ctrl_ctratt) -{ - __u32 ctratt = le32_to_cpu(ctrl_ctratt); - __u32 rsvd20 = (ctratt >> 20); - __u32 fdps = (ctratt >> 19) & 0x1; - __u32 rsvd16 = (ctratt >> 16) & 0x7; - __u32 elbas = (ctratt >> 15) & 0x1; - __u32 delnvmset = (ctratt >> 14) & 0x1; - __u32 delegrp = (ctratt >> 13) & 0x1; - __u32 vcap = (ctratt >> 12) & 0x1; - __u32 fcap = (ctratt >> 11) & 0x1; - __u32 mds = (ctratt >> 10) & 0x1; - __u32 hostid128 = (ctratt & NVME_CTRL_CTRATT_128_ID) >> 0; - __u32 psp = (ctratt & NVME_CTRL_CTRATT_NON_OP_PSP) >> 1; - __u32 sets = (ctratt & NVME_CTRL_CTRATT_NVM_SETS) >> 2; - __u32 rrl = (ctratt & NVME_CTRL_CTRATT_READ_RECV_LVLS) >> 3; - __u32 eg = (ctratt & NVME_CTRL_CTRATT_ENDURANCE_GROUPS) >> 4; - __u32 iod = (ctratt & NVME_CTRL_CTRATT_PREDICTABLE_LAT) >> 5; - __u32 tbkas = (ctratt & NVME_CTRL_CTRATT_TBKAS) >> 6; - __u32 ng = (ctratt & NVME_CTRL_CTRATT_NAMESPACE_GRANULARITY) >> 7; - __u32 sqa = (ctratt & NVME_CTRL_CTRATT_SQ_ASSOCIATIONS) >> 8; - __u32 uuidlist = (ctratt & NVME_CTRL_CTRATT_UUID_LIST) >> 9; - - if (rsvd20) - printf(" [31:20] : %#x\tReserved\n", rsvd20); - printf(" [19:19] : %#x\tFlexible Data Placement %sSupported\n", - fdps, fdps ? "" : "Not "); - if (rsvd16) - printf(" [18:16] : %#x\tReserved\n", rsvd16); - printf(" [15:15] : %#x\tExtended LBA Formats %sSupported\n", - elbas, elbas ? "" : "Not "); - printf(" [14:14] : %#x\tDelete NVM Set %sSupported\n", - delnvmset, delnvmset ? "" : "Not "); - printf(" [13:13] : %#x\tDelete Endurance Group %sSupported\n", - delegrp, delegrp ? "" : "Not "); - printf(" [12:12] : %#x\tVariable Capacity Management %sSupported\n", - vcap, vcap ? "" : "Not "); - printf(" [11:11] : %#x\tFixed Capacity Management %sSupported\n", - fcap, fcap ? "" : "Not "); - printf(" [10:10] : %#x\tMulti Domain Subsystem %sSupported\n", - mds, mds ? "" : "Not "); - printf(" [9:9] : %#x\tUUID List %sSupported\n", - uuidlist, uuidlist ? "" : "Not "); - printf(" [8:8] : %#x\tSQ Associations %sSupported\n", - sqa, sqa ? "" : "Not "); - printf(" [7:7] : %#x\tNamespace Granularity %sSupported\n", - ng, ng ? "" : "Not "); - printf(" [6:6] : %#x\tTraffic Based Keep Alive %sSupported\n", - tbkas, tbkas ? "" : "Not "); - printf(" [5:5] : %#x\tPredictable Latency Mode %sSupported\n", - iod, iod ? "" : "Not "); - printf(" [4:4] : %#x\tEndurance Groups %sSupported\n", - eg, eg ? "" : "Not "); - printf(" [3:3] : %#x\tRead Recovery Levels %sSupported\n", - rrl, rrl ? "" : "Not "); - printf(" [2:2] : %#x\tNVM Sets %sSupported\n", - sets, sets ? "" : "Not "); - printf(" [1:1] : %#x\tNon-Operational Power State Permissive %sSupported\n", - psp, psp ? "" : "Not "); - printf(" [0:0] : %#x\t128-bit Host Identifier %sSupported\n", - hostid128, hostid128 ? "" : "Not "); - printf("\n"); -} - -static void nvme_show_id_ctrl_cntrltype(__u8 cntrltype) -{ - __u8 rsvd = (cntrltype & 0xFC) >> 2; - __u8 cntrl = cntrltype & 0x3; - - static const char *type[] = { - "Controller type not reported", - "I/O Controller", - "Discovery Controller", - "Administrative Controller" - }; - - printf(" [7:2] : %#x\tReserved\n", rsvd); - printf(" [1:0] : %#x\t%s\n", cntrltype, type[cntrl]); -} - -static void nvme_show_id_ctrl_nvmsr(__u8 nvmsr) -{ - __u8 rsvd = (nvmsr >> 2) & 0xfc; - __u8 nvmee = (nvmsr >> 1) & 0x1; - __u8 nvmesd = nvmsr & 0x1; - - if (rsvd) - printf(" [7:2] : %#x\tReserved\n", rsvd); - printf(" [1:1] : %#x\tNVM subsystem %spart of an Enclosure\n", - nvmee, nvmee ? "" : "Not "); - printf(" [0:0] : %#x\tNVM subsystem %spart of a Storage Device\n", - nvmesd, nvmesd ? "" : "Not "); - printf("\n"); -} - -static void nvme_show_id_ctrl_vwci(__u8 vwci) -{ - __u8 vwcrv = (vwci >> 7) & 0x1; - __u8 vwcr = vwci & 0xfe; - - printf(" [7:7] : %#x\tVPD Write Cycles Remaining field is %svalid.\n", - vwcrv, vwcrv ? "" : "Not "); - printf(" [6:0] : %#x\tVPD Write Cycles Remaining \n", vwcr); - printf("\n"); - -} - -static void nvme_show_id_ctrl_mec(__u8 mec) -{ - __u8 rsvd = (mec >> 2) & 0xfc; - __u8 pcieme = (mec >> 1) & 0x1; - __u8 smbusme = mec & 0x1; - - if (rsvd) - printf(" [7:2] : %#x\tReserved\n", rsvd); - printf(" [1:1] : %#x\tNVM subsystem %scontains a Management Endpoint"\ - " on a PCIe port\n", pcieme, pcieme ? "" : "Not "); - printf(" [0:0] : %#x\tNVM subsystem %scontains a Management Endpoint"\ - " on an SMBus/I2C port\n", smbusme, smbusme ? "" : "Not "); - printf("\n"); - -} - -static void nvme_show_id_ctrl_oacs(__le16 ctrl_oacs) -{ - __u16 oacs = le16_to_cpu(ctrl_oacs); - __u16 rsvd = (oacs & 0xF800) >> 11; - __u16 lock = (oacs >> 10) & 0x1; - __u16 glbas = (oacs & 0x200) >> 9; - __u16 dbc = (oacs & 0x100) >> 8; - __u16 vir = (oacs & 0x80) >> 7; - __u16 nmi = (oacs & 0x40) >> 6; - __u16 dir = (oacs & 0x20) >> 5; - __u16 sft = (oacs & 0x10) >> 4; - __u16 nsm = (oacs & 0x8) >> 3; - __u16 fwc = (oacs & 0x4) >> 2; - __u16 fmt = (oacs & 0x2) >> 1; - __u16 sec = oacs & 0x1; - - if (rsvd) - printf(" [15:11] : %#x\tReserved\n", rsvd); - printf(" [10:10] : %#x\tLockdown Command and Feature %sSupported\n", - lock, lock ? "" : "Not "); - printf(" [9:9] : %#x\tGet LBA Status Capability %sSupported\n", - glbas, glbas ? "" : "Not "); - printf(" [8:8] : %#x\tDoorbell Buffer Config %sSupported\n", - dbc, dbc ? "" : "Not "); - printf(" [7:7] : %#x\tVirtualization Management %sSupported\n", - vir, vir ? "" : "Not "); - printf(" [6:6] : %#x\tNVMe-MI Send and Receive %sSupported\n", - nmi, nmi ? "" : "Not "); - printf(" [5:5] : %#x\tDirectives %sSupported\n", - dir, dir ? "" : "Not "); - printf(" [4:4] : %#x\tDevice Self-test %sSupported\n", - sft, sft ? "" : "Not "); - printf(" [3:3] : %#x\tNS Management and Attachment %sSupported\n", - nsm, nsm ? "" : "Not "); - printf(" [2:2] : %#x\tFW Commit and Download %sSupported\n", - fwc, fwc ? "" : "Not "); - printf(" [1:1] : %#x\tFormat NVM %sSupported\n", - fmt, fmt ? "" : "Not "); - printf(" [0:0] : %#x\tSecurity Send and Receive %sSupported\n", - sec, sec ? "" : "Not "); - printf("\n"); -} - -static void nvme_show_id_ctrl_frmw(__u8 frmw) -{ - __u8 rsvd = (frmw & 0xC0) >> 6; - __u8 smud = (frmw >> 5) & 0x1; - __u8 fawr = (frmw & 0x10) >> 4; - __u8 nfws = (frmw & 0xE) >> 1; - __u8 s1ro = frmw & 0x1; - - if (rsvd) - printf(" [7:6] : %#x\tReserved\n", rsvd); - printf(" [5:5] : %#x\tMultiple FW or Boot Update Detection %sSupported\n", - smud, smud ? "" : "Not "); - printf(" [4:4] : %#x\tFirmware Activate Without Reset %sSupported\n", - fawr, fawr ? "" : "Not "); - printf(" [3:1] : %#x\tNumber of Firmware Slots\n", nfws); - printf(" [0:0] : %#x\tFirmware Slot 1 Read%s\n", - s1ro, s1ro ? "-Only" : "/Write"); - printf("\n"); -} - -static void nvme_show_id_ctrl_lpa(__u8 lpa) -{ - __u8 rsvd = (lpa & 0x80) >> 7; - __u8 tel = (lpa >> 6) & 0x1; - __u8 lid_sup = (lpa >> 5) & 0x1; - __u8 persevnt = (lpa & 0x10) >> 4; - __u8 telem = (lpa & 0x8) >> 3; - __u8 ed = (lpa & 0x4) >> 2; - __u8 celp = (lpa & 0x2) >> 1; - __u8 smlp = lpa & 0x1; - - if (rsvd) - printf(" [7:7] : %#x\tReserved\n", rsvd); - printf(" [6:6] : %#x\tTelemetry Log Data Area 4 %sSupported\n", - tel, tel ? "" : "Not "); - printf(" [5:5] : %#x\tLID 0x0, Scope of each command in LID 0x5, "\ - "0x12, 0x13 %sSupported\n", lid_sup, lid_sup ? "" : "Not "); - printf(" [4:4] : %#x\tPersistent Event log %sSupported\n", - persevnt, persevnt ? "" : "Not "); - printf(" [3:3] : %#x\tTelemetry host/controller initiated log page %sSupported\n", - telem, telem ? "" : "Not "); - printf(" [2:2] : %#x\tExtended data for Get Log Page %sSupported\n", - ed, ed ? "" : "Not "); - printf(" [1:1] : %#x\tCommand Effects Log Page %sSupported\n", - celp, celp ? "" : "Not "); - printf(" [0:0] : %#x\tSMART/Health Log Page per NS %sSupported\n", - smlp, smlp ? "" : "Not "); - printf("\n"); -} - -static void nvme_show_id_ctrl_elpe(__u8 elpe) -{ - printf(" [7:0] : %d (0's based)\tError Log Page Entries (ELPE)\n", - elpe); - printf("\n"); -} - -static void nvme_show_id_ctrl_npss(__u8 npss) -{ - printf(" [7:0] : %d (0's based)\tNumber of Power States Support (NPSS)\n", - npss); - printf("\n"); -} - -static void nvme_show_id_ctrl_avscc(__u8 avscc) -{ - __u8 rsvd = (avscc & 0xFE) >> 1; - __u8 fmt = avscc & 0x1; - if (rsvd) - printf(" [7:1] : %#x\tReserved\n", rsvd); - printf(" [0:0] : %#x\tAdmin Vendor Specific Commands uses %s Format\n", - fmt, fmt ? "NVMe" : "Vendor Specific"); - printf("\n"); -} - -static void nvme_show_id_ctrl_apsta(__u8 apsta) -{ - __u8 rsvd = (apsta & 0xFE) >> 1; - __u8 apst = apsta & 0x1; - if (rsvd) - printf(" [7:1] : %#x\tReserved\n", rsvd); - printf(" [0:0] : %#x\tAutonomous Power State Transitions %sSupported\n", - apst, apst ? "" : "Not "); - printf("\n"); -} - -static void nvme_show_id_ctrl_wctemp(__le16 wctemp) -{ - printf(" [15:0] : %ld °C (%u K)\tWarning Composite Temperature Threshold (WCTEMP)\n", - kelvin_to_celsius(le16_to_cpu(wctemp)), le16_to_cpu(wctemp)); - printf("\n"); -} - -static void nvme_show_id_ctrl_cctemp(__le16 cctemp) -{ - printf(" [15:0] : %ld °C (%u K)\tCritical Composite Temperature Threshold (CCTEMP)\n", - kelvin_to_celsius(le16_to_cpu(cctemp)), le16_to_cpu(cctemp)); - printf("\n"); -} - -static void nvme_show_id_ctrl_tnvmcap(__u8 *tnvmcap) -{ - printf("[127:0] : %s\n", uint128_t_to_l10n_string(le128_to_cpu(tnvmcap))); - printf("\tTotal NVM Capacity (TNVMCAP)\n\n"); -} - -static void nvme_show_id_ctrl_unvmcap(__u8 *unvmcap) -{ - printf("[127:0] : %s\n", uint128_t_to_l10n_string(le128_to_cpu(unvmcap))); - printf("\tUnallocated NVM Capacity (UNVMCAP)\n\n"); -} - -void nvme_show_id_ctrl_rpmbs(__le32 ctrl_rpmbs, enum nvme_print_flags flags) -{ - __u32 rpmbs = le32_to_cpu(ctrl_rpmbs); - __u32 asz = (rpmbs & 0xFF000000) >> 24; - __u32 tsz = (rpmbs & 0xFF0000) >> 16; - __u32 rsvd = (rpmbs & 0xFFC0) >> 6; - __u32 auth = (rpmbs & 0x38) >> 3; - __u32 rpmb = rpmbs & 0x7; - - nvme_print(id_ctrl_rpmbs, flags, ctrl_rpmbs); - - printf(" [31:24]: %#x\tAccess Size\n", asz); - printf(" [23:16]: %#x\tTotal Size\n", tsz); - if (rsvd) - printf(" [15:6] : %#x\tReserved\n", rsvd); - printf(" [5:3] : %#x\tAuthentication Method\n", auth); - printf(" [2:0] : %#x\tNumber of RPMB Units\n", rpmb); - printf("\n"); -} - -static void nvme_show_id_ctrl_hctma(__le16 ctrl_hctma) -{ - __u16 hctma = le16_to_cpu(ctrl_hctma); - __u16 rsvd = (hctma & 0xFFFE) >> 1; - __u16 hctm = hctma & 0x1; - - if (rsvd) - printf(" [15:1] : %#x\tReserved\n", rsvd); - printf(" [0:0] : %#x\tHost Controlled Thermal Management %sSupported\n", - hctm, hctm ? "" : "Not "); - printf("\n"); -} - -static void nvme_show_id_ctrl_mntmt(__le16 mntmt) -{ - printf(" [15:0] : %ld °C (%u K)\tMinimum Thermal Management Temperature (MNTMT)\n", - kelvin_to_celsius(le16_to_cpu(mntmt)), le16_to_cpu(mntmt)); - printf("\n"); -} - -static void nvme_show_id_ctrl_mxtmt(__le16 mxtmt) -{ - printf(" [15:0] : %ld °C (%u K)\tMaximum Thermal Management Temperature (MXTMT)\n", - kelvin_to_celsius(le16_to_cpu(mxtmt)), le16_to_cpu(mxtmt)); - printf("\n"); -} - -static void nvme_show_id_ctrl_sanicap(__le32 ctrl_sanicap) -{ - __u32 sanicap = le32_to_cpu(ctrl_sanicap); - __u32 rsvd = (sanicap & 0x1FFFFFF8) >> 3; - __u32 owr = (sanicap & 0x4) >> 2; - __u32 ber = (sanicap & 0x2) >> 1; - __u32 cer = sanicap & 0x1; - __u32 ndi = (sanicap & 0x20000000) >> 29; - __u32 nodmmas = (sanicap & 0xC0000000) >> 30; - - static const char *modifies_media[] = { - "Additional media modification after sanitize operation completes successfully is not defined", - "Media is not additionally modified after sanitize operation completes successfully", - "Media is additionally modified after sanitize operation completes successfully", - "Reserved" - }; - - printf(" [31:30] : %#x\t%s\n", nodmmas, modifies_media[nodmmas]); - printf(" [29:29] : %#x\tNo-Deallocate After Sanitize bit in Sanitize command %sSupported\n", - ndi, ndi ? "Not " : ""); - if (rsvd) - printf(" [28:3] : %#x\tReserved\n", rsvd); - printf(" [2:2] : %#x\tOverwrite Sanitize Operation %sSupported\n", - owr, owr ? "" : "Not "); - printf(" [1:1] : %#x\tBlock Erase Sanitize Operation %sSupported\n", - ber, ber ? "" : "Not "); - printf(" [0:0] : %#x\tCrypto Erase Sanitize Operation %sSupported\n", - cer, cer ? "" : "Not "); - printf("\n"); -} - -static void nvme_show_id_ctrl_anacap(__u8 anacap) -{ - __u8 nz = (anacap & 0x80) >> 7; - __u8 grpid_static = (anacap & 0x40) >> 6; - __u8 rsvd = (anacap & 0x20) >> 5; - __u8 ana_change = (anacap & 0x10) >> 4; - __u8 ana_persist_loss = (anacap & 0x08) >> 3; - __u8 ana_inaccessible = (anacap & 0x04) >> 2; - __u8 ana_nonopt = (anacap & 0x02) >> 1; - __u8 ana_opt = (anacap & 0x01); - - printf(" [7:7] : %#x\tNon-zero group ID %sSupported\n", - nz, nz ? "" : "Not "); - printf(" [6:6] : %#x\tGroup ID does %schange\n", - grpid_static, grpid_static ? "not " : ""); - if (rsvd) - printf(" [5:5] : %#x\tReserved\n", rsvd); - printf(" [4:4] : %#x\tANA Change state %sSupported\n", - ana_change, ana_change ? "" : "Not "); - printf(" [3:3] : %#x\tANA Persistent Loss state %sSupported\n", - ana_persist_loss, ana_persist_loss ? "" : "Not "); - printf(" [2:2] : %#x\tANA Inaccessible state %sSupported\n", - ana_inaccessible, ana_inaccessible ? "" : "Not "); - printf(" [1:1] : %#x\tANA Non-optimized state %sSupported\n", - ana_nonopt, ana_nonopt ? "" : "Not "); - printf(" [0:0] : %#x\tANA Optimized state %sSupported\n", - ana_opt, ana_opt ? "" : "Not "); - printf("\n"); -} - -static void nvme_show_id_ctrl_sqes(__u8 sqes) -{ - __u8 msqes = (sqes & 0xF0) >> 4; - __u8 rsqes = sqes & 0xF; - printf(" [7:4] : %#x\tMax SQ Entry Size (%d)\n", msqes, 1 << msqes); - printf(" [3:0] : %#x\tMin SQ Entry Size (%d)\n", rsqes, 1 << rsqes); - printf("\n"); -} - -static void nvme_show_id_ctrl_cqes(__u8 cqes) -{ - __u8 mcqes = (cqes & 0xF0) >> 4; - __u8 rcqes = cqes & 0xF; - printf(" [7:4] : %#x\tMax CQ Entry Size (%d)\n", mcqes, 1 << mcqes); - printf(" [3:0] : %#x\tMin CQ Entry Size (%d)\n", rcqes, 1 << rcqes); - printf("\n"); -} - -static void nvme_show_id_ctrl_oncs(__le16 ctrl_oncs) -{ - __u16 oncs = le16_to_cpu(ctrl_oncs); - __u16 rsvd = (oncs & 0xFE00) >> 9; - __u16 copy = (oncs & 0x100) >> 8; - __u16 vrfy = (oncs & 0x80) >> 7; - __u16 tmst = (oncs & 0x40) >> 6; - __u16 resv = (oncs & 0x20) >> 5; - __u16 save = (oncs & 0x10) >> 4; - __u16 wzro = (oncs & 0x8) >> 3; - __u16 dsms = (oncs & 0x4) >> 2; - __u16 wunc = (oncs & 0x2) >> 1; - __u16 cmp = oncs & 0x1; - - if (rsvd) - printf(" [15:9] : %#x\tReserved\n", rsvd); - printf(" [8:8] : %#x\tCopy %sSupported\n", - copy, copy ? "" : "Not "); - printf(" [7:7] : %#x\tVerify %sSupported\n", - vrfy, vrfy ? "" : "Not "); - printf(" [6:6] : %#x\tTimestamp %sSupported\n", - tmst, tmst ? "" : "Not "); - printf(" [5:5] : %#x\tReservations %sSupported\n", - resv, resv ? "" : "Not "); - printf(" [4:4] : %#x\tSave and Select %sSupported\n", - save, save ? "" : "Not "); - printf(" [3:3] : %#x\tWrite Zeroes %sSupported\n", - wzro, wzro ? "" : "Not "); - printf(" [2:2] : %#x\tData Set Management %sSupported\n", - dsms, dsms ? "" : "Not "); - printf(" [1:1] : %#x\tWrite Uncorrectable %sSupported\n", - wunc, wunc ? "" : "Not "); - printf(" [0:0] : %#x\tCompare %sSupported\n", - cmp, cmp ? "" : "Not "); - printf("\n"); -} - -static void nvme_show_id_ctrl_fuses(__le16 ctrl_fuses) -{ - __u16 fuses = le16_to_cpu(ctrl_fuses); - __u16 rsvd = (fuses & 0xFE) >> 1; - __u16 cmpw = fuses & 0x1; - - if (rsvd) - printf(" [15:1] : %#x\tReserved\n", rsvd); - printf(" [0:0] : %#x\tFused Compare and Write %sSupported\n", - cmpw, cmpw ? "" : "Not "); - printf("\n"); -} - -static void nvme_show_id_ctrl_fna(__u8 fna) -{ - __u8 rsvd = (fna & 0xF0) >> 4; - __u8 bcnsid = (fna & 0x8) >> 3; - __u8 cese = (fna & 0x4) >> 2; - __u8 cens = (fna & 0x2) >> 1; - __u8 fmns = fna & 0x1; - if (rsvd) - printf(" [7:4] : %#x\tReserved\n", rsvd); - printf(" [3:3] : %#x\tFormat NVM Broadcast NSID (FFFFFFFFh) %sSupported\n", - bcnsid, bcnsid ? "Not " : ""); - printf(" [2:2] : %#x\tCrypto Erase %sSupported as part of Secure Erase\n", - cese, cese ? "" : "Not "); - printf(" [1:1] : %#x\tCrypto Erase Applies to %s Namespace(s)\n", - cens, cens ? "All" : "Single"); - printf(" [0:0] : %#x\tFormat Applies to %s Namespace(s)\n", - fmns, fmns ? "All" : "Single"); - printf("\n"); -} - -static void nvme_show_id_ctrl_vwc(__u8 vwc) -{ - __u8 rsvd = (vwc & 0xF8) >> 3; - __u8 flush = (vwc & 0x6) >> 1; - __u8 vwcp = vwc & 0x1; - - static const char *flush_behavior[] = { - "Support for the NSID field set to FFFFFFFFh is not indicated", - "Reserved", - "The Flush command does not support NSID set to FFFFFFFFh", - "The Flush command supports NSID set to FFFFFFFFh" - }; - - if (rsvd) - printf(" [7:3] : %#x\tReserved\n", rsvd); - printf(" [2:1] : %#x\t%s\n", flush, flush_behavior[flush]); - printf(" [0:0] : %#x\tVolatile Write Cache %sPresent\n", - vwcp, vwcp ? "" : "Not "); - printf("\n"); -} - -static void nvme_show_id_ctrl_icsvscc(__u8 icsvscc) -{ - __u8 rsvd = (icsvscc & 0xFE) >> 1; - __u8 fmt = icsvscc & 0x1; - if (rsvd) - printf(" [7:1] : %#x\tReserved\n", rsvd); - printf(" [0:0] : %#x\tNVM Vendor Specific Commands uses %s Format\n", - fmt, fmt ? "NVMe" : "Vendor Specific"); - printf("\n"); -} - -static void nvme_show_id_ctrl_nwpc(__u8 nwpc) -{ - __u8 no_wp_wp = (nwpc & 0x01); - __u8 wp_power_cycle = (nwpc & 0x02) >> 1; - __u8 wp_permanent = (nwpc & 0x04) >> 2; - __u8 rsvd = (nwpc & 0xF8) >> 3; - - if (rsvd) - printf(" [7:3] : %#x\tReserved\n", rsvd); - - printf(" [2:2] : %#x\tPermanent Write Protect %sSupported\n", - wp_permanent, wp_permanent ? "" : "Not "); - printf(" [1:1] : %#x\tWrite Protect Until Power Supply %sSupported\n", - wp_power_cycle, wp_power_cycle ? "" : "Not "); - printf(" [0:0] : %#x\tNo Write Protect and Write Protect Namespace %sSupported\n", - no_wp_wp, no_wp_wp ? "" : "Not "); - printf("\n"); -} - -static void nvme_show_id_ctrl_ocfs(__le16 ctrl_ocfs) -{ - __u16 ocfs = le16_to_cpu(ctrl_ocfs); - __u16 rsvd = (ocfs & 0xfffc) >> 2; - __u8 copy_fmt_1 = (ocfs >> 1) & 0x1; - __u8 copy_fmt_0 = ocfs & 0x1; - if (rsvd) - printf(" [15:2] : %#x\tReserved\n", rsvd); - printf(" [1:1] : %#x\tController Copy Format 1h %sSupported\n", - copy_fmt_1, copy_fmt_1 ? "" : "Not "); - printf(" [0:0] : %#x\tController Copy Format 0h %sSupported\n", - copy_fmt_0, copy_fmt_0 ? "" : "Not "); - printf("\n"); -} - -static void nvme_show_id_ctrl_sgls(__le32 ctrl_sgls) -{ - __u32 sgls = le32_to_cpu(ctrl_sgls); - __u32 rsvd0 = (sgls & 0xFFC00000) >> 22; - __u32 trsdbd = (sgls & 0x200000) >> 21; - __u32 aofdsl = (sgls & 0x100000) >> 20; - __u32 mpcsd = (sgls & 0x80000) >> 19; - __u32 sglltb = (sgls & 0x40000) >> 18; - __u32 bacmdb = (sgls & 0x20000) >> 17; - __u32 bbs = (sgls & 0x10000) >> 16; - __u32 sdt = (sgls >> 8) & 0xff; - __u32 rsvd1 = (sgls & 0xF8) >> 3; - __u32 key = (sgls & 0x4) >> 2; - __u32 sglsp = sgls & 0x3; - - if (rsvd0) - printf(" [31:22]: %#x\tReserved\n", rsvd0); - if (sglsp || (!sglsp && trsdbd)) - printf(" [21:21]: %#x\tTransport SGL Data Block Descriptor %sSupported\n", - trsdbd, trsdbd ? "" : "Not "); - if (sglsp || (!sglsp && aofdsl)) - printf(" [20:20]: %#x\tAddress Offsets %sSupported\n", - aofdsl, aofdsl ? "" : "Not "); - if (sglsp || (!sglsp && mpcsd)) - printf(" [19:19]: %#x\tMetadata Pointer Containing " - "SGL Descriptor is %sSupported\n", - mpcsd, mpcsd ? "" : "Not "); - if (sglsp || (!sglsp && sglltb)) - printf(" [18:18]: %#x\tSGL Length Larger than Buffer %sSupported\n", - sglltb, sglltb ? "" : "Not "); - if (sglsp || (!sglsp && bacmdb)) - printf(" [17:17]: %#x\tByte-Aligned Contig. MD Buffer %sSupported\n", - bacmdb, bacmdb ? "" : "Not "); - if (sglsp || (!sglsp && bbs)) - printf(" [16:16]: %#x\tSGL Bit-Bucket %sSupported\n", - bbs, bbs ? "" : "Not "); - printf(" [15:8] : %#x\tSGL Descriptor Threshold\n", sdt); - if (rsvd1) - printf(" [7:3] : %#x\tReserved\n", rsvd1); - if (sglsp || (!sglsp && key)) - printf(" [2:2] : %#x\tKeyed SGL Data Block descriptor %sSupported\n", - key, key ? "" : "Not "); - if (sglsp == 0x3) - printf(" [1:0] : %#x\tReserved\n", sglsp); - else if (sglsp == 0x2) - printf(" [1:0] : %#x\tScatter-Gather Lists Supported." - " Dword alignment required.\n", sglsp); - else if (sglsp == 0x1) - printf(" [1:0] : %#x\tScatter-Gather Lists Supported." - " No Dword alignment required.\n", sglsp); - else - printf(" [1:0] : %#x\tScatter-Gather Lists Not Supported\n", sglsp); - printf("\n"); -} - -static void nvme_show_id_ctrl_fcatt(__u8 fcatt) -{ - __u8 rsvd = (fcatt & 0xFE) >> 1; - __u8 scm = fcatt & 0x1; - if (rsvd) - printf(" [7:1] : %#x\tReserved\n", rsvd); - printf(" [0:0] : %#x\t%s Controller Model\n", - scm, scm ? "Static" : "Dynamic"); - printf("\n"); -} - -static void nvme_show_id_ctrl_ofcs(__le16 ofcs) -{ - __u16 rsvd = (ofcs & 0xfffe) >> 1; - __u8 disconn = ofcs & 0x1; - if (rsvd) - printf(" [15:1] : %#x\tReserved\n", rsvd); - printf(" [0:0] : %#x\tDisconnect command %s Supported\n", - disconn, disconn ? "" : "Not"); - printf("\n"); - -} - -static void nvme_show_id_ns_nsfeat(__u8 nsfeat) -{ - __u8 rsvd = (nsfeat & 0xE0) >> 5; - __u8 ioopt = (nsfeat & 0x10) >> 4; - __u8 uidreuse = (nsfeat & 0x8) >> 3; - __u8 dulbe = (nsfeat & 0x4) >> 2; - __u8 na = (nsfeat & 0x2) >> 1; - __u8 thin = nsfeat & 0x1; - if (rsvd) - printf(" [7:5] : %#x\tReserved\n", rsvd); - printf(" [4:4] : %#x\tNPWG, NPWA, NPDG, NPDA, and NOWS are %sSupported\n", - ioopt, ioopt ? "" : "Not "); - printf(" [3:3] : %#x\tNGUID and EUI64 fields if non-zero, %sReused\n", - uidreuse, uidreuse ? "Never " : ""); - printf(" [2:2] : %#x\tDeallocated or Unwritten Logical Block error %sSupported\n", - dulbe, dulbe ? "" : "Not "); - printf(" [1:1] : %#x\tNamespace uses %s\n", - na, na ? "NAWUN, NAWUPF, and NACWU" : "AWUN, AWUPF, and ACWU"); - printf(" [0:0] : %#x\tThin Provisioning %sSupported\n", - thin, thin ? "" : "Not "); - printf("\n"); -} - -static void nvme_show_id_ns_flbas(__u8 flbas) -{ - __u8 rsvd = (flbas & 0x80) >> 7; - __u8 msb2_lbaf = (flbas & NVME_NS_FLBAS_HIGHER_MASK) >> 5; - __u8 mdedata = (flbas & 0x10) >> 4; - __u8 lsb4_lbaf = flbas & NVME_NS_FLBAS_LOWER_MASK; - - if (rsvd) - printf(" [7:7] : %#x\tReserved\n", rsvd); - printf(" [6:5] : %#x\tMost significant 2 bits of Current LBA Format Selected\n", - msb2_lbaf); - printf(" [4:4] : %#x\tMetadata Transferred %s\n", - mdedata, mdedata ? "at End of Data LBA" : "in Separate Contiguous Buffer"); - printf(" [3:0] : %#x\tLeast significant 4 bits of Current LBA Format Selected\n", - lsb4_lbaf); - printf("\n"); -} - -static void nvme_show_id_ns_mc(__u8 mc) -{ - __u8 rsvd = (mc & 0xFC) >> 2; - __u8 mdp = (mc & 0x2) >> 1; - __u8 extdlba = mc & 0x1; - if (rsvd) - printf(" [7:2] : %#x\tReserved\n", rsvd); - printf(" [1:1] : %#x\tMetadata Pointer %sSupported\n", - mdp, mdp ? "" : "Not "); - printf(" [0:0] : %#x\tMetadata as Part of Extended Data LBA %sSupported\n", - extdlba, extdlba ? "" : "Not "); - printf("\n"); -} - -static void nvme_show_id_ns_dpc(__u8 dpc) -{ - __u8 rsvd = (dpc & 0xE0) >> 5; - __u8 pil8 = (dpc & 0x10) >> 4; - __u8 pif8 = (dpc & 0x8) >> 3; - __u8 pit3 = (dpc & 0x4) >> 2; - __u8 pit2 = (dpc & 0x2) >> 1; - __u8 pit1 = dpc & 0x1; - if (rsvd) - printf(" [7:5] : %#x\tReserved\n", rsvd); - printf(" [4:4] : %#x\tProtection Information Transferred as Last 8 Bytes of Metadata %sSupported\n", - pil8, pil8 ? "" : "Not "); - printf(" [3:3] : %#x\tProtection Information Transferred as First 8 Bytes of Metadata %sSupported\n", - pif8, pif8 ? "" : "Not "); - printf(" [2:2] : %#x\tProtection Information Type 3 %sSupported\n", - pit3, pit3 ? "" : "Not "); - printf(" [1:1] : %#x\tProtection Information Type 2 %sSupported\n", - pit2, pit2 ? "" : "Not "); - printf(" [0:0] : %#x\tProtection Information Type 1 %sSupported\n", - pit1, pit1 ? "" : "Not "); - printf("\n"); -} - -static void nvme_show_id_ns_dps(__u8 dps) -{ - __u8 rsvd = (dps & 0xF0) >> 4; - __u8 pif8 = (dps & 0x8) >> 3; - __u8 pit = dps & 0x7; - if (rsvd) - printf(" [7:4] : %#x\tReserved\n", rsvd); - printf(" [3:3] : %#x\tProtection Information is Transferred as %s 8 Bytes of Metadata\n", - pif8, pif8 ? "First" : "Last"); - printf(" [2:0] : %#x\tProtection Information %s\n", pit, - pit == 3 ? "Type 3 Enabled" : - pit == 2 ? "Type 2 Enabled" : - pit == 1 ? "Type 1 Enabled" : - pit == 0 ? "Disabled" : "Reserved Enabled"); - printf("\n"); -} - -static void nvme_show_id_ns_nmic(__u8 nmic) -{ - __u8 rsvd = (nmic & 0xFE) >> 1; - __u8 mp = nmic & 0x1; - if (rsvd) - printf(" [7:1] : %#x\tReserved\n", rsvd); - printf(" [0:0] : %#x\tNamespace Multipath %sCapable\n", - mp, mp ? "" : "Not "); - printf("\n"); -} - -static void nvme_show_id_ns_rescap(__u8 rescap) -{ - __u8 iekr = (rescap & 0x80) >> 7; - __u8 eaar = (rescap & 0x40) >> 6; - __u8 wear = (rescap & 0x20) >> 5; - __u8 earo = (rescap & 0x10) >> 4; - __u8 wero = (rescap & 0x8) >> 3; - __u8 ea = (rescap & 0x4) >> 2; - __u8 we = (rescap & 0x2) >> 1; - __u8 ptpl = rescap & 0x1; - - printf(" [7:7] : %#x\tIgnore Existing Key - Used as defined in revision %s\n", - iekr, iekr ? "1.3 or later" : "1.2.1 or earlier"); - printf(" [6:6] : %#x\tExclusive Access - All Registrants %sSupported\n", - eaar, eaar ? "" : "Not "); - printf(" [5:5] : %#x\tWrite Exclusive - All Registrants %sSupported\n", - wear, wear ? "" : "Not "); - printf(" [4:4] : %#x\tExclusive Access - Registrants Only %sSupported\n", - earo, earo ? "" : "Not "); - printf(" [3:3] : %#x\tWrite Exclusive - Registrants Only %sSupported\n", - wero, wero ? "" : "Not "); - printf(" [2:2] : %#x\tExclusive Access %sSupported\n", - ea, ea ? "" : "Not "); - printf(" [1:1] : %#x\tWrite Exclusive %sSupported\n", - we, we ? "" : "Not "); - printf(" [0:0] : %#x\tPersist Through Power Loss %sSupported\n", - ptpl, ptpl ? "" : "Not "); - printf("\n"); -} - -static void nvme_show_id_ns_fpi(__u8 fpi) -{ - __u8 fpis = (fpi & 0x80) >> 7; - __u8 fpii = fpi & 0x7F; - printf(" [7:7] : %#x\tFormat Progress Indicator %sSupported\n", - fpis, fpis ? "" : "Not "); - if (fpis || (!fpis && fpii)) - printf(" [6:0] : %#x\tFormat Progress Indicator (Remaining %d%%)\n", - fpii, fpii); - printf("\n"); -} - -static void nvme_show_id_ns_nsattr(__u8 nsattr) -{ - __u8 rsvd = (nsattr & 0xFE) >> 1; - __u8 write_protected = nsattr & 0x1; - if (rsvd) - printf(" [7:1] : %#x\tReserved\n", rsvd); - printf(" [0:0] : %#x\tNamespace %sWrite Protected\n", - write_protected, write_protected ? "" : "Not "); - printf("\n"); -} - -static void nvme_show_id_ns_dlfeat(__u8 dlfeat) -{ - __u8 rsvd = (dlfeat & 0xE0) >> 5; - __u8 guard = (dlfeat & 0x10) >> 4; - __u8 dwz = (dlfeat & 0x8) >> 3; - __u8 val = dlfeat & 0x7; - if (rsvd) - printf(" [7:5] : %#x\tReserved\n", rsvd); - printf(" [4:4] : %#x\tGuard Field of Deallocated Logical Blocks is set to %s\n", - guard, guard ? "CRC of The Value Read" : "0xFFFF"); - printf(" [3:3] : %#x\tDeallocate Bit in the Write Zeroes Command is %sSupported\n", - dwz, dwz ? "" : "Not "); - printf(" [2:0] : %#x\tBytes Read From a Deallocated Logical Block and its Metadata are %s\n", - val, val == 2 ? "0xFF" : - val == 1 ? "0x00" : - val == 0 ? "Not Reported" : "Reserved Value"); - printf("\n"); -} - -void nvme_show_id_ns(struct nvme_id_ns *ns, unsigned int nsid, - unsigned int lba_index, bool cap_only, enum nvme_print_flags flags) -{ - bool human = flags & VERBOSE; - int vs = flags & VS; - int i; - __u8 flbas; - char *in_use = "(in use)"; - - nvme_print(id_ns, flags, ns, nsid, lba_index, cap_only); - - if (flags & BINARY) - return d_raw((unsigned char *)ns, sizeof(*ns)); - - if (!cap_only) { - printf("NVME Identify Namespace %d:\n", nsid); - printf("nsze : %#"PRIx64"\n", le64_to_cpu(ns->nsze)); - printf("ncap : %#"PRIx64"\n", le64_to_cpu(ns->ncap)); - printf("nuse : %#"PRIx64"\n", le64_to_cpu(ns->nuse)); - printf("nsfeat : %#x\n", ns->nsfeat); - if (human) - nvme_show_id_ns_nsfeat(ns->nsfeat); - } else - printf("NVMe Identify Namespace for LBA format[%d]:\n", lba_index); - - printf("nlbaf : %d\n", ns->nlbaf); - if (!cap_only) { - printf("flbas : %#x\n", ns->flbas); - if (human) - nvme_show_id_ns_flbas(ns->flbas); - } else - in_use = ""; - - printf("mc : %#x\n", ns->mc); - if (human) - nvme_show_id_ns_mc(ns->mc); - printf("dpc : %#x\n", ns->dpc); - if (human) - nvme_show_id_ns_dpc(ns->dpc); - if (!cap_only) { - printf("dps : %#x\n", ns->dps); - if (human) - nvme_show_id_ns_dps(ns->dps); - printf("nmic : %#x\n", ns->nmic); - if (human) - nvme_show_id_ns_nmic(ns->nmic); - printf("rescap : %#x\n", ns->rescap); - if (human) - nvme_show_id_ns_rescap(ns->rescap); - printf("fpi : %#x\n", ns->fpi); - if (human) - nvme_show_id_ns_fpi(ns->fpi); - printf("dlfeat : %d\n", ns->dlfeat); - if (human) - nvme_show_id_ns_dlfeat(ns->dlfeat); - printf("nawun : %d\n", le16_to_cpu(ns->nawun)); - printf("nawupf : %d\n", le16_to_cpu(ns->nawupf)); - printf("nacwu : %d\n", le16_to_cpu(ns->nacwu)); - printf("nabsn : %d\n", le16_to_cpu(ns->nabsn)); - printf("nabo : %d\n", le16_to_cpu(ns->nabo)); - printf("nabspf : %d\n", le16_to_cpu(ns->nabspf)); - printf("noiob : %d\n", le16_to_cpu(ns->noiob)); - printf("nvmcap : %s\n", - uint128_t_to_l10n_string(le128_to_cpu(ns->nvmcap))); - if (ns->nsfeat & 0x10) { - printf("npwg : %u\n", le16_to_cpu(ns->npwg)); - printf("npwa : %u\n", le16_to_cpu(ns->npwa)); - printf("npdg : %u\n", le16_to_cpu(ns->npdg)); - printf("npda : %u\n", le16_to_cpu(ns->npda)); - printf("nows : %u\n", le16_to_cpu(ns->nows)); - } - printf("mssrl : %u\n", le16_to_cpu(ns->mssrl)); - printf("mcl : %u\n", le32_to_cpu(ns->mcl)); - printf("msrc : %u\n", ns->msrc); - } - printf("nulbaf : %u\n", ns->nulbaf); - if (!cap_only) { - printf("anagrpid: %u\n", le32_to_cpu(ns->anagrpid)); - printf("nsattr : %u\n", ns->nsattr); - printf("nvmsetid: %d\n", le16_to_cpu(ns->nvmsetid)); - printf("endgid : %d\n", le16_to_cpu(ns->endgid)); - - printf("nguid : "); - for (i = 0; i < 16; i++) - printf("%02x", ns->nguid[i]); - printf("\n"); - - printf("eui64 : "); - for (i = 0; i < 8; i++) - printf("%02x", ns->eui64[i]); - printf("\n"); - } - - nvme_id_ns_flbas_to_lbaf_inuse(ns->flbas, &flbas); - for (i = 0; i <= ns->nlbaf + ns->nulbaf; i++) { - if (human) - printf("LBA Format %2d : Metadata Size: %-3d bytes - " - "Data Size: %-2d bytes - Relative Performance: %#x %s %s\n", - i, le16_to_cpu(ns->lbaf[i].ms), - 1 << ns->lbaf[i].ds, ns->lbaf[i].rp, - ns->lbaf[i].rp == 3 ? "Degraded" : - ns->lbaf[i].rp == 2 ? "Good" : - ns->lbaf[i].rp == 1 ? "Better" : "Best", - i == flbas ? in_use : ""); - else - printf("lbaf %2d : ms:%-3d lbads:%-2d rp:%#x %s\n", i, - le16_to_cpu(ns->lbaf[i].ms), ns->lbaf[i].ds, - ns->lbaf[i].rp, i == flbas ? in_use : ""); - } - - if (vs && !cap_only) { - printf("vs[]:\n"); - d(ns->vs, sizeof(ns->vs), 16, 1); - } -} - -static void nvme_show_cmd_set_independent_id_ns_nsfeat(__u8 nsfeat) -{ - __u8 rsvd6 = (nsfeat & 0xE0) >> 6; - __u8 vwcnp = (nsfeat & 0x20) >> 5; - __u8 rmedia = (nsfeat & 0x10) >> 4; - __u8 uidreuse = (nsfeat & 0x8) >> 3; - __u8 rsvd0 = (nsfeat & 0x7); - if (rsvd6) - printf(" [7:6] : %#x\tReserved\n", rsvd6); - printf(" [5:5] : %#x\tVolatile Write Cache is %sPresent\n", - vwcnp, vwcnp ? "" : "Not "); - printf(" [4:4] : %#x\tNamespace %sstore data on rotational media\n", - rmedia, rmedia ? "" : "does not "); - printf(" [3:3] : %#x\tNGUID and EUI64 fields if non-zero, %sReused\n", - uidreuse, uidreuse ? "Never " : ""); - if (rsvd0) - printf(" [2:0] : %#x\tReserved\n", rsvd0); - printf("\n"); -} - -static void nvme_show_cmd_set_independent_id_ns_nstat(__u8 nstat) -{ - __u8 rsvd1 = (nstat & 0xfe) >> 1; - __u8 nrdy = nstat & 0x1; - if (rsvd1) - printf(" [7:1] : %#x\tReserved\n", rsvd1); - printf(" [0:0] : %#x\tName space is %sready\n", - nrdy, nrdy ? "" : "not "); - printf("\n"); -} - -void nvme_show_cmd_set_independent_id_ns( - struct nvme_id_independent_id_ns *ns, unsigned int nsid, - enum nvme_print_flags flags) -{ - int human = flags & VERBOSE; - - nvme_print(id_independent_id_ns, flags, ns, nsid); - - if (flags & BINARY) - return d_raw((unsigned char *)ns, sizeof(*ns)); - - printf("NVME Identify Command Set Independent Namespace %d:\n", nsid); - printf("nsfeat : %#x\n", ns->nsfeat); - if (human) - nvme_show_cmd_set_independent_id_ns_nsfeat(ns->nsfeat); - printf("nmic : %#x\n", ns->nmic); - if (human) - nvme_show_id_ns_nmic(ns->nmic); - printf("rescap : %#x\n", ns->rescap); - if (human) - nvme_show_id_ns_rescap(ns->rescap); - printf("fpi : %#x\n", ns->fpi); - if (human) - nvme_show_id_ns_fpi(ns->fpi); - printf("anagrpid: %u\n", le32_to_cpu(ns->anagrpid)); - printf("nsattr : %u\n", ns->nsattr); - if (human) - nvme_show_id_ns_nsattr(ns->nsattr); - printf("nvmsetid: %d\n", le16_to_cpu(ns->nvmsetid)); - printf("endgid : %d\n", le16_to_cpu(ns->endgid)); - - printf("nstat : %#x\n", ns->nstat); - if (human) - nvme_show_cmd_set_independent_id_ns_nstat(ns->nstat); -} - -void nvme_show_id_ns_descs(void *data, unsigned nsid, enum nvme_print_flags flags) -{ - int pos, len = 0; - int i; - __u8 uuid[NVME_UUID_LEN]; - char uuid_str[NVME_UUID_LEN_STRING]; - __u8 eui64[8]; - __u8 nguid[16]; - __u8 csi; - - nvme_print(id_ns_descs, flags, data, nsid); - - if (flags & BINARY) - return d_raw((unsigned char *)data, 0x1000); - - printf("NVME Namespace Identification Descriptors NS %d:\n", nsid); - for (pos = 0; pos < NVME_IDENTIFY_DATA_SIZE; pos += len) { - struct nvme_ns_id_desc *cur = data + pos; - - if (cur->nidl == 0) - break; - - switch (cur->nidt) { - case NVME_NIDT_EUI64: - memcpy(eui64, data + pos + sizeof(*cur), sizeof(eui64)); - printf("eui64 : "); - for (i = 0; i < 8; i++) - printf("%02x", eui64[i]); - printf("\n"); - len = sizeof(eui64); - break; - case NVME_NIDT_NGUID: - memcpy(nguid, data + pos + sizeof(*cur), sizeof(nguid)); - printf("nguid : "); - for (i = 0; i < 16; i++) - printf("%02x", nguid[i]); - printf("\n"); - len = sizeof(nguid); - break; - case NVME_NIDT_UUID: - memcpy(uuid, data + pos + sizeof(*cur), 16); - nvme_uuid_to_string(uuid, uuid_str); - printf("uuid : %s\n", uuid_str); - len = sizeof(uuid); - break; - case NVME_NIDT_CSI: - memcpy(&csi, data + pos + sizeof(*cur), 1); - printf("csi : %#x\n", csi); - len += sizeof(csi); - break; - default: - /* Skip unknown types */ - len = cur->nidl; - break; - } - - len += sizeof(*cur); - } -} - -static void print_psd_workload(__u8 apw) -{ - switch (apw & 0x7) { - case NVME_PSD_WORKLOAD_NP: - /* Unknown or not provided */ - printf("-"); - break; - - case 1: - /* Extended idle period with burst of random write */ - printf("1MiB 32 RW, 30s idle"); - break; - - case 2: - /* Heavy sequential writes */ - printf("80K 128KiB SW"); - break; - - default: - printf("reserved"); - } -} - -static void print_ps_power_and_scale(__le16 ctr_power, __u8 scale) -{ - __u16 power = le16_to_cpu(ctr_power); - - switch (scale & 0x3) { - case NVME_PSD_PS_NOT_REPORTED: - /* Not reported for this power state */ - printf("-"); - break; - - case NVME_PSD_PS_100_MICRO_WATT: - /* Units of 0.0001W */ - printf("%01u.%04uW", power / 10000, power % 10000); - break; - - case NVME_PSD_PS_10_MILLI_WATT: - /* Units of 0.01W */ - printf("%01u.%02uW", power / 100, power % 100); - break; - - default: - printf("reserved"); - } -} - -static void nvme_show_id_ctrl_power(struct nvme_id_ctrl *ctrl) -{ - int i; - - for (i = 0; i <= ctrl->npss; i++) { - __u16 max_power = le16_to_cpu(ctrl->psd[i].mp); - - printf("ps %4d : mp:", i); - - if (ctrl->psd[i].flags & NVME_PSD_FLAGS_MXPS) - printf("%01u.%04uW ", max_power / 10000, max_power % 10000); - else - printf("%01u.%02uW ", max_power / 100, max_power % 100); - - if (ctrl->psd[i].flags & NVME_PSD_FLAGS_NOPS) - printf("non-"); - - printf("operational enlat:%d exlat:%d rrt:%d rrl:%d\n" - " rwt:%d rwl:%d idle_power:", - le32_to_cpu(ctrl->psd[i].enlat), - le32_to_cpu(ctrl->psd[i].exlat), - ctrl->psd[i].rrt, ctrl->psd[i].rrl, - ctrl->psd[i].rwt, ctrl->psd[i].rwl); - print_ps_power_and_scale(ctrl->psd[i].idlp, - nvme_psd_power_scale(ctrl->psd[i].ips)); - printf(" active_power:"); - print_ps_power_and_scale(ctrl->psd[i].actp, - nvme_psd_power_scale(ctrl->psd[i].apws)); - printf("\n active_power_workload:"); - print_psd_workload(ctrl->psd[i].apws); - printf("\n"); - - } -} - -void nvme_show_id_ctrl(struct nvme_id_ctrl *ctrl, enum nvme_print_flags flags, - void (*vendor_show)(__u8 *vs, struct json_object *root)) -{ - bool human = flags & VERBOSE, vs = flags & VS; - - nvme_print(id_ctrl, flags, ctrl, vendor_show); - - if (flags & BINARY) - return d_raw((unsigned char *)ctrl, sizeof(*ctrl)); - - printf("NVME Identify Controller:\n"); - printf("vid : %#x\n", le16_to_cpu(ctrl->vid)); - printf("ssvid : %#x\n", le16_to_cpu(ctrl->ssvid)); - printf("sn : %-.*s\n", (int)sizeof(ctrl->sn), ctrl->sn); - printf("mn : %-.*s\n", (int)sizeof(ctrl->mn), ctrl->mn); - printf("fr : %-.*s\n", (int)sizeof(ctrl->fr), ctrl->fr); - printf("rab : %d\n", ctrl->rab); - printf("ieee : %02x%02x%02x\n", - ctrl->ieee[2], ctrl->ieee[1], ctrl->ieee[0]); - printf("cmic : %#x\n", ctrl->cmic); - if (human) - nvme_show_id_ctrl_cmic(ctrl->cmic); - printf("mdts : %d\n", ctrl->mdts); - printf("cntlid : %#x\n", le16_to_cpu(ctrl->cntlid)); - printf("ver : %#x\n", le32_to_cpu(ctrl->ver)); - printf("rtd3r : %#x\n", le32_to_cpu(ctrl->rtd3r)); - printf("rtd3e : %#x\n", le32_to_cpu(ctrl->rtd3e)); - printf("oaes : %#x\n", le32_to_cpu(ctrl->oaes)); - if (human) - nvme_show_id_ctrl_oaes(ctrl->oaes); - printf("ctratt : %#x\n", le32_to_cpu(ctrl->ctratt)); - if (human) - nvme_show_id_ctrl_ctratt(ctrl->ctratt); - printf("rrls : %#x\n", le16_to_cpu(ctrl->rrls)); - printf("cntrltype : %d\n", ctrl->cntrltype); - if (human) - nvme_show_id_ctrl_cntrltype(ctrl->cntrltype); - printf("fguid : %s\n", util_uuid_to_string(ctrl->fguid)); - printf("crdt1 : %u\n", le16_to_cpu(ctrl->crdt1)); - printf("crdt2 : %u\n", le16_to_cpu(ctrl->crdt2)); - printf("crdt3 : %u\n", le16_to_cpu(ctrl->crdt3)); - printf("nvmsr : %u\n", ctrl->nvmsr); - if (human) - nvme_show_id_ctrl_nvmsr(ctrl->nvmsr); - printf("vwci : %u\n", ctrl->vwci); - if (human) - nvme_show_id_ctrl_vwci(ctrl->vwci); - printf("mec : %u\n", ctrl->mec); - if (human) - nvme_show_id_ctrl_mec(ctrl->mec); - - printf("oacs : %#x\n", le16_to_cpu(ctrl->oacs)); - if (human) - nvme_show_id_ctrl_oacs(ctrl->oacs); - printf("acl : %d\n", ctrl->acl); - printf("aerl : %d\n", ctrl->aerl); - printf("frmw : %#x\n", ctrl->frmw); - if (human) - nvme_show_id_ctrl_frmw(ctrl->frmw); - printf("lpa : %#x\n", ctrl->lpa); - if (human) - nvme_show_id_ctrl_lpa(ctrl->lpa); - printf("elpe : %d\n", ctrl->elpe); - if (human) - nvme_show_id_ctrl_elpe(ctrl->elpe); - printf("npss : %d\n", ctrl->npss); - if (human) - nvme_show_id_ctrl_npss(ctrl->npss); - printf("avscc : %#x\n", ctrl->avscc); - if (human) - nvme_show_id_ctrl_avscc(ctrl->avscc); - printf("apsta : %#x\n", ctrl->apsta); - if (human) - nvme_show_id_ctrl_apsta(ctrl->apsta); - printf("wctemp : %d\n", le16_to_cpu(ctrl->wctemp)); - if (human) - nvme_show_id_ctrl_wctemp(ctrl->wctemp); - printf("cctemp : %d\n", le16_to_cpu(ctrl->cctemp)); - if (human) - nvme_show_id_ctrl_cctemp(ctrl->cctemp); - printf("mtfa : %d\n", le16_to_cpu(ctrl->mtfa)); - printf("hmpre : %u\n", le32_to_cpu(ctrl->hmpre)); - printf("hmmin : %u\n", le32_to_cpu(ctrl->hmmin)); - printf("tnvmcap : %s\n", - uint128_t_to_l10n_string(le128_to_cpu(ctrl->tnvmcap))); - if (human) - nvme_show_id_ctrl_tnvmcap(ctrl->tnvmcap); - printf("unvmcap : %s\n", - uint128_t_to_l10n_string(le128_to_cpu(ctrl->unvmcap))); - if (human) - nvme_show_id_ctrl_unvmcap(ctrl->unvmcap); - printf("rpmbs : %#x\n", le32_to_cpu(ctrl->rpmbs)); - if (human) - nvme_show_id_ctrl_rpmbs(ctrl->rpmbs, flags); - printf("edstt : %d\n", le16_to_cpu(ctrl->edstt)); - printf("dsto : %d\n", ctrl->dsto); - printf("fwug : %d\n", ctrl->fwug); - printf("kas : %d\n", le16_to_cpu(ctrl->kas)); - printf("hctma : %#x\n", le16_to_cpu(ctrl->hctma)); - if (human) - nvme_show_id_ctrl_hctma(ctrl->hctma); - printf("mntmt : %d\n", le16_to_cpu(ctrl->mntmt)); - if (human) - nvme_show_id_ctrl_mntmt(ctrl->mntmt); - printf("mxtmt : %d\n", le16_to_cpu(ctrl->mxtmt)); - if (human) - nvme_show_id_ctrl_mxtmt(ctrl->mxtmt); - printf("sanicap : %#x\n", le32_to_cpu(ctrl->sanicap)); - if (human) - nvme_show_id_ctrl_sanicap(ctrl->sanicap); - printf("hmminds : %u\n", le32_to_cpu(ctrl->hmminds)); - printf("hmmaxd : %d\n", le16_to_cpu(ctrl->hmmaxd)); - printf("nsetidmax : %d\n", le16_to_cpu(ctrl->nsetidmax)); - printf("endgidmax : %d\n", le16_to_cpu(ctrl->endgidmax)); - printf("anatt : %d\n", ctrl->anatt); - printf("anacap : %d\n", ctrl->anacap); - if (human) - nvme_show_id_ctrl_anacap(ctrl->anacap); - printf("anagrpmax : %u\n", ctrl->anagrpmax); - printf("nanagrpid : %u\n", le32_to_cpu(ctrl->nanagrpid)); - printf("pels : %u\n", le32_to_cpu(ctrl->pels)); - printf("domainid : %d\n", le16_to_cpu(ctrl->domainid)); - printf("megcap : %s\n", - uint128_t_to_l10n_string(le128_to_cpu(ctrl->megcap))); - printf("sqes : %#x\n", ctrl->sqes); - if (human) - nvme_show_id_ctrl_sqes(ctrl->sqes); - printf("cqes : %#x\n", ctrl->cqes); - if (human) - nvme_show_id_ctrl_cqes(ctrl->cqes); - printf("maxcmd : %d\n", le16_to_cpu(ctrl->maxcmd)); - printf("nn : %u\n", le32_to_cpu(ctrl->nn)); - printf("oncs : %#x\n", le16_to_cpu(ctrl->oncs)); - if (human) - nvme_show_id_ctrl_oncs(ctrl->oncs); - printf("fuses : %#x\n", le16_to_cpu(ctrl->fuses)); - if (human) - nvme_show_id_ctrl_fuses(ctrl->fuses); - printf("fna : %#x\n", ctrl->fna); - if (human) - nvme_show_id_ctrl_fna(ctrl->fna); - printf("vwc : %#x\n", ctrl->vwc); - if (human) - nvme_show_id_ctrl_vwc(ctrl->vwc); - printf("awun : %d\n", le16_to_cpu(ctrl->awun)); - printf("awupf : %d\n", le16_to_cpu(ctrl->awupf)); - printf("icsvscc : %d\n", ctrl->icsvscc); - if (human) - nvme_show_id_ctrl_icsvscc(ctrl->icsvscc); - printf("nwpc : %d\n", ctrl->nwpc); - if (human) - nvme_show_id_ctrl_nwpc(ctrl->nwpc); - printf("acwu : %d\n", le16_to_cpu(ctrl->acwu)); - printf("ocfs : %#x\n", le16_to_cpu(ctrl->ocfs)); - if (human) - nvme_show_id_ctrl_ocfs(ctrl->ocfs); - printf("sgls : %#x\n", le32_to_cpu(ctrl->sgls)); - if (human) - nvme_show_id_ctrl_sgls(ctrl->sgls); - printf("mnan : %u\n", le32_to_cpu(ctrl->mnan)); - printf("maxdna : %s\n", - uint128_t_to_l10n_string(le128_to_cpu(ctrl->maxdna))); - printf("maxcna : %u\n", le32_to_cpu(ctrl->maxcna)); - printf("subnqn : %-.*s\n", (int)sizeof(ctrl->subnqn), ctrl->subnqn); - printf("ioccsz : %u\n", le32_to_cpu(ctrl->ioccsz)); - printf("iorcsz : %u\n", le32_to_cpu(ctrl->iorcsz)); - printf("icdoff : %d\n", le16_to_cpu(ctrl->icdoff)); - printf("fcatt : %#x\n", ctrl->fcatt); - if (human) - nvme_show_id_ctrl_fcatt(ctrl->fcatt); - printf("msdbd : %d\n", ctrl->msdbd); - printf("ofcs : %d\n", le16_to_cpu(ctrl->ofcs)); - if (human) - nvme_show_id_ctrl_ofcs(ctrl->ofcs); - - nvme_show_id_ctrl_power(ctrl); - if (vendor_show) - vendor_show(ctrl->vs, NULL); - else if (vs) { - printf("vs[]:\n"); - d(ctrl->vs, sizeof(ctrl->vs), 16, 1); - } + if (flags & BINARY) + return d_raw((unsigned char *)ctrl, sizeof(*ctrl)); } void nvme_show_id_ctrl_nvm(struct nvme_id_ctrl_nvm *ctrl_nvm, @@ -3202,73 +536,16 @@ void nvme_show_id_ctrl_nvm(struct nvme_id_ctrl_nvm *ctrl_nvm, if (flags & BINARY) return d_raw((unsigned char *)ctrl_nvm, sizeof(*ctrl_nvm)); - - printf("NVMe Identify Controller NVM:\n"); - printf("vsl : %u\n", ctrl_nvm->vsl); - printf("wzsl : %u\n", ctrl_nvm->wzsl); - printf("wusl : %u\n", ctrl_nvm->wusl); - printf("dmrl : %u\n", ctrl_nvm->dmrl); - printf("dmrsl : %u\n", le32_to_cpu(ctrl_nvm->dmrsl)); - printf("dmsl : %"PRIu64"\n", le64_to_cpu(ctrl_nvm->dmsl)); -} - -static void nvme_show_nvm_id_ns_pic(__u8 pic) -{ - __u8 rsvd = (pic & 0xF8) >> 3; - __u8 stcrs = (pic & 0x3) >> 2; - __u8 pic_16bpistm = (pic & 0x2) >> 1; - __u8 pic_16bpists = pic & 0x1; - - if (rsvd) - printf(" [7:3] : %#x\tReserved\n", rsvd); - printf(" [2:2] : %#x\tStorage Tag Check Read Support\n", stcrs); - printf(" [1:1] : %#x\t16b Guard Protection Information Storage Tag Mask\n", - pic_16bpistm); - printf(" [0:0] : %#x\t16b Guard Protection Information Storage Tag Support\n", - pic_16bpists); - printf("\n"); } void nvme_show_nvm_id_ns(struct nvme_nvm_id_ns *nvm_ns, unsigned int nsid, struct nvme_id_ns *ns, unsigned int lba_index, bool cap_only, enum nvme_print_flags flags) { - int i, verbose = flags & VERBOSE; - __u32 elbaf; - int pif, sts; - char *in_use = "(in use)"; - nvme_print(nvm_id_ns, flags, nvm_ns, nsid, ns, lba_index, cap_only); if (flags & BINARY) return d_raw((unsigned char *)nvm_ns, sizeof(*nvm_ns)); - - if (!cap_only) { - printf("NVMe NVM Identify Namespace %d:\n", nsid); - printf("lbstm : %#"PRIx64"\n", le64_to_cpu(nvm_ns->lbstm)); - } else { - printf("NVMe NVM Identify Namespace for LBA format[%d]:\n", lba_index); - in_use = ""; - } - printf("pic : %#x\n", nvm_ns->pic); - if (verbose) - nvme_show_nvm_id_ns_pic(nvm_ns->pic); - - for (i = 0; i <= ns->nlbaf + ns->nulbaf; i++) { - elbaf = le32_to_cpu(nvm_ns->elbaf[i]); - pif = (elbaf >> 7) & 0x3; - sts = elbaf & 0x7f; - if (verbose) - printf("Extended LBA Format %2d : Protection Information Format: " - "%s(%d) - Storage Tag Size (MSB): %-2d %s\n", - i, pif == 3 ? "Reserved" : - pif == 2 ? "64b Guard" : - pif == 1 ? "32b Guard" : "16b Guard", - pif, sts, i == (ns->flbas & 0xf) ? in_use : ""); - else - printf("elbaf %2d : pif:%d lbads:%-2d %s\n", i, - pif, sts, i == (ns->flbas & 0xf) ? in_use : ""); - } } void nvme_show_zns_id_ctrl(struct nvme_zns_id_ctrl *ctrl, @@ -3278,184 +555,30 @@ void nvme_show_zns_id_ctrl(struct nvme_zns_id_ctrl *ctrl, if (flags & BINARY) return d_raw((unsigned char *)ctrl, sizeof(*ctrl)); - - printf("NVMe ZNS Identify Controller:\n"); - printf("zasl : %u\n", ctrl->zasl); -} - -static void show_nvme_id_ns_zoned_zoc(__le16 ns_zoc) -{ - __u16 zoc = le16_to_cpu(ns_zoc); - __u8 rsvd = (zoc & 0xfffc) >> 2; - __u8 ze = (zoc & 0x2) >> 1; - __u8 vzc = zoc & 0x1; - if (rsvd) - printf(" [15:2] : %#x\tReserved\n", rsvd); - printf(" [1:1] : %#x\t Zone Active Excursions: %s\n", - ze, ze ? "Yes (Host support required)" : "No"); - printf(" [0:0] : %#x\t Variable Zone Capacity: %s\n", - vzc, vzc ? "Yes (Host support required)" : "No"); - printf("\n"); -} - -static void show_nvme_id_ns_zoned_ozcs(__le16 ns_ozcs) -{ - __u16 ozcs = le16_to_cpu(ns_ozcs); - __u8 rsvd = (ozcs & 0xfffc) >> 2; - __u8 razb = ozcs & 0x1; - __u8 zrwasup = (ozcs & 0x2) >> 1; - - if (rsvd) - printf(" [15:1] : %#x\tReserved\n", rsvd); - printf(" [0:0] : %#x\t Read Across Zone Boundaries: %s\n", - razb, razb ? "Yes" : "No"); - printf(" [1:1] : %#x\t Zone Random Write Area: %s\n", zrwasup, - zrwasup ? "Yes" : "No"); -} - -static void nvme_show_zns_id_ns_recommended_limit(__le32 ns_rl, int human, - const char *target_limit) -{ - unsigned int recommended_limit = le32_to_cpu(ns_rl); - if (!recommended_limit && human) - printf("%s : Not Reported\n", target_limit); - else - printf("%s : %u\n", target_limit, recommended_limit); -} - -static void nvme_show_zns_id_ns_zrwacap(__u8 zrwacap) -{ - __u8 rsvd = (zrwacap & 0xfe) >> 1; - __u8 expflushsup = zrwacap & 0x1; - - if (rsvd) - printf(" [7:1] : %#x\tReserved\n", rsvd); - printf(" [0:0] : %#x\t Explicit ZRWA Flush Operations: %s\n", - expflushsup, expflushsup ? "Yes" : "No"); } void nvme_show_zns_id_ns(struct nvme_zns_id_ns *ns, struct nvme_id_ns *id_ns, enum nvme_print_flags flags) { - int human = flags & VERBOSE, vs = flags & VS; - uint8_t lbaf; - int i; - - nvme_id_ns_flbas_to_lbaf_inuse(id_ns->flbas, &lbaf); - nvme_print(zns_id_ns, flags, ns, id_ns); if (flags & BINARY) return d_raw((unsigned char *)ns, sizeof(*ns)); - - printf("ZNS Command Set Identify Namespace:\n"); - - if (human) { - printf("zoc : %u\tZone Operation Characteristics\n", le16_to_cpu(ns->zoc)); - show_nvme_id_ns_zoned_zoc(ns->zoc); - } else { - printf("zoc : %u\n", le16_to_cpu(ns->zoc)); - } - - if (human) { - printf("ozcs : %u\tOptional Zoned Command Support\n", le16_to_cpu(ns->ozcs)); - show_nvme_id_ns_zoned_ozcs(ns->ozcs); - } else { - printf("ozcs : %u\n", le16_to_cpu(ns->ozcs)); - } - - if (human) { - if (ns->mar == 0xffffffff) { - printf("mar : No Active Resource Limit\n"); - } else { - printf("mar : %u\tActive Resources\n", le32_to_cpu(ns->mar) + 1); - } - } else { - printf("mar : %#x\n", le32_to_cpu(ns->mar)); - } - - if (human) { - if (ns->mor == 0xffffffff) { - printf("mor : No Open Resource Limit\n"); - } else { - printf("mor : %u\tOpen Resources\n", le32_to_cpu(ns->mor) + 1); - } - } else { - printf("mor : %#x\n", le32_to_cpu(ns->mor)); - } - - nvme_show_zns_id_ns_recommended_limit(ns->rrl, human, "rrl "); - nvme_show_zns_id_ns_recommended_limit(ns->frl, human, "frl "); - nvme_show_zns_id_ns_recommended_limit(ns->rrl1, human, "rrl1"); - nvme_show_zns_id_ns_recommended_limit(ns->rrl2, human, "rrl2"); - nvme_show_zns_id_ns_recommended_limit(ns->rrl3, human, "rrl3"); - nvme_show_zns_id_ns_recommended_limit(ns->frl, human, "frl1"); - nvme_show_zns_id_ns_recommended_limit(ns->frl, human, "frl2"); - nvme_show_zns_id_ns_recommended_limit(ns->frl, human, "frl3"); - - printf("numzrwa : %#x\n", le32_to_cpu(ns->numzrwa)); - printf("zrwafg : %u\n", le16_to_cpu(ns->zrwafg)); - printf("zrwasz : %u\n", le16_to_cpu(ns->zrwasz)); - if (human) { - printf("zrwacap : %u\tZone Random Write Area Capability\n", ns->zrwacap); - nvme_show_zns_id_ns_zrwacap(ns->zrwacap); - } else { - printf("zrwacap : %u\n", ns->zrwacap); - } - - for (i = 0; i <= id_ns->nlbaf; i++){ - if (human) - printf("LBA Format Extension %2d : Zone Size: 0x%"PRIx64" LBAs - " - "Zone Descriptor Extension Size: %-1d bytes%s\n", - i, le64_to_cpu(ns->lbafe[i].zsze), ns->lbafe[i].zdes << 6, - i == lbaf ? " (in use)" : ""); - else - printf("lbafe %2d: zsze:0x%"PRIx64" zdes:%u%s\n", i, - (uint64_t)le64_to_cpu(ns->lbafe[i].zsze), - ns->lbafe[i].zdes, i == lbaf ? " (in use)" : ""); - } - - if (vs) { - printf("vs[] :\n"); - d(ns->vs, sizeof(ns->vs), 16, 1); - } } void nvme_show_list_ns(struct nvme_ns_list *ns_list, enum nvme_print_flags flags) { - int i; - nvme_print(ns_list, flags, ns_list); - - for (i = 0; i < 1024; i++) { - if (ns_list->ns[i]) - printf("[%4u]:%#x\n", i, le32_to_cpu(ns_list->ns[i])); - } } void nvme_show_zns_changed(struct nvme_zns_changed_zone_log *log, enum nvme_print_flags flags) { - uint16_t nrzid; - int i; - nvme_print(zns_changed_zone_log, flags, log); if (flags & BINARY) return d_raw((unsigned char *)log, sizeof(*log)); - - nrzid = le16_to_cpu(log->nrzid); - printf("NVMe Changed Zone List:\n"); - - if (nrzid == 0xFFFF) { - printf("Too many zones have changed to fit into the log. Use report zones for changes.\n"); - return; - } - - printf("nrzid: %u\n", nrzid); - for (i = 0; i < nrzid; i++) - printf("zid %03d: %"PRIu64"\n", i, (uint64_t)le64_to_cpu(log->zid[i])); } const char *nvme_zone_type_to_string(__u8 cond) @@ -3490,325 +613,96 @@ const char *nvme_zone_state_to_string(__u8 state) } } -static void nvme_show_zns_report_zone_attributes(__u8 za, __u8 zai) -{ - const char *const recommended_limit[4] = {"","1","2","3"}; - printf("Attrs: Zone Descriptor Extension is %sVaild\n", - (za & NVME_ZNS_ZA_ZDEV)? "" : "Not "); - if(za & NVME_ZNS_ZA_RZR) { - printf(" Reset Zone Recommended with Reset Recommended Limit%s\n", - recommended_limit[(zai&0xd)>>2]); - } - if (za & NVME_ZNS_ZA_FZR) { - printf(" Finish Zone Recommended with Finish Recommended Limit%s\n", - recommended_limit[zai&0x3]); - } - if (za & NVME_ZNS_ZA_ZFC) { - printf(" Zone Finished by Controller\n"); - } -} - void nvme_show_zns_report_zones(void *report, __u32 descs, __u8 ext_size, __u32 report_size, struct json_object *zone_list, enum nvme_print_flags flags) { - struct nvme_zone_report *r = report; - struct nvme_zns_desc *desc; - int i, verbose = flags & VERBOSE; - __u64 nr_zones = le64_to_cpu(r->nr_zones); - - if (nr_zones < descs) - descs = nr_zones; - nvme_print(zns_report_zones, flags, report, descs, ext_size, report_size, zone_list); - if (flags & BINARY) - return d_raw((unsigned char *)report, report_size); - - for (i = 0; i < descs; i++) { - desc = (struct nvme_zns_desc *) - (report + sizeof(*r) + i * (sizeof(*desc) + ext_size)); - if(verbose) { - printf("SLBA: %#-10"PRIx64" WP: %#-10"PRIx64" Cap: %#-10"PRIx64" State: %-12s Type: %-14s\n", - (uint64_t)le64_to_cpu(desc->zslba), (uint64_t)le64_to_cpu(desc->wp), - (uint64_t)le64_to_cpu(desc->zcap), nvme_zone_state_to_string(desc->zs >> 4), - nvme_zone_type_to_string(desc->zt)); - nvme_show_zns_report_zone_attributes(desc->za, desc->zai); - } - else { - printf("SLBA: %#-10"PRIx64" WP: %#-10"PRIx64" Cap: %#-10"PRIx64" State: %#-4x Type: %#-4x Attrs: %#-4x AttrsInfo: %#-4x\n", - (uint64_t)le64_to_cpu(desc->zslba), (uint64_t)le64_to_cpu(desc->wp), - (uint64_t)le64_to_cpu(desc->zcap), desc->zs, desc->zt, - desc->za, desc->zai); - } - - if (ext_size && (desc->za & NVME_ZNS_ZA_ZDEV)) { - printf("Extension Data: "); - d((unsigned char *)desc + sizeof(*desc), ext_size, 16, 1); - printf("..\n"); - } - } + if (flags & BINARY) + return d_raw((unsigned char *)report, report_size); } void nvme_show_list_ctrl(struct nvme_ctrl_list *ctrl_list, enum nvme_print_flags flags) { - int i; __u16 num = le16_to_cpu(ctrl_list->num); nvme_print(ctrl_list, flags, ctrl_list, num); if (flags & BINARY) return d_raw((unsigned char *)ctrl_list, sizeof(*ctrl_list)); - - printf("num of ctrls present: %u\n", num); - for (i = 0; i < min(num, 2047); i++) { - printf("[%4u]:%#x\n", i, le16_to_cpu(ctrl_list->identifier[i])); - } } void nvme_show_id_nvmset(struct nvme_id_nvmset_list *nvmset, unsigned nvmset_id, enum nvme_print_flags flags) { - int i; - - if (flags & BINARY) return d_raw((unsigned char *)nvmset, sizeof(*nvmset)); nvme_print(id_nvmset_list, flags, nvmset, nvmset_id); - - printf("NVME Identify NVM Set List %d:\n", nvmset_id); - printf("nid : %d\n", nvmset->nid); - printf(".................\n"); - for (i = 0; i < nvmset->nid; i++) { - printf(" NVM Set Attribute Entry[%2d]\n", i); - printf(".................\n"); - printf("nvmset_id : %d\n", - le16_to_cpu(nvmset->ent[i].endgid)); - printf("endurance_group_id : %d\n", - le16_to_cpu(nvmset->ent[i].endgid)); - printf("random_4k_read_typical : %u\n", - le32_to_cpu(nvmset->ent[i].rr4kt)); - printf("optimal_write_size : %u\n", - le32_to_cpu(nvmset->ent[i].ows)); - printf("total_nvmset_cap : %s\n", - uint128_t_to_l10n_string( - le128_to_cpu(nvmset->ent[i].tnvmsetcap))); - printf("unalloc_nvmset_cap : %s\n", - uint128_t_to_l10n_string( - le128_to_cpu(nvmset->ent[i].unvmsetcap))); - printf(".................\n"); - } -} - -static void nvme_show_primary_ctrl_caps_crt(__u8 crt) -{ - __u8 rsvd = (crt & 0xFC) >> 2; - __u8 vi = (crt & 0x2) >> 1; - __u8 vq = crt & 0x1; - - if (rsvd) - printf(" [7:2] : %#x\tReserved\n", rsvd); - printf(" [1:1] %#x\tVI Resources are %ssupported\n", vi, vi ? "" : "not "); - printf(" [0:0] %#x\tVQ Resources are %ssupported\n", vq, vq ? "" : "not "); } void nvme_show_primary_ctrl_cap(const struct nvme_primary_ctrl_cap *caps, enum nvme_print_flags flags) { - int human = flags & VERBOSE; - nvme_print(primary_ctrl_cap, flags, caps); if (flags & BINARY) return d_raw((unsigned char *)caps, sizeof(*caps)); - - printf("NVME Identify Primary Controller Capabilities:\n"); - printf("cntlid : %#x\n", le16_to_cpu(caps->cntlid)); - printf("portid : %#x\n", le16_to_cpu(caps->portid)); - printf("crt : %#x\n", caps->crt); - if (human) - nvme_show_primary_ctrl_caps_crt(caps->crt); - printf("vqfrt : %u\n", le32_to_cpu(caps->vqfrt)); - printf("vqrfa : %u\n", le32_to_cpu(caps->vqrfa)); - printf("vqrfap : %d\n", le16_to_cpu(caps->vqrfap)); - printf("vqprt : %d\n", le16_to_cpu(caps->vqprt)); - printf("vqfrsm : %d\n", le16_to_cpu(caps->vqfrsm)); - printf("vqgran : %d\n", le16_to_cpu(caps->vqgran)); - printf("vifrt : %u\n", le32_to_cpu(caps->vifrt)); - printf("virfa : %u\n", le32_to_cpu(caps->virfa)); - printf("virfap : %d\n", le16_to_cpu(caps->virfap)); - printf("viprt : %d\n", le16_to_cpu(caps->viprt)); - printf("vifrsm : %d\n", le16_to_cpu(caps->vifrsm)); - printf("vigran : %d\n", le16_to_cpu(caps->vigran)); } void nvme_show_list_secondary_ctrl( const struct nvme_secondary_ctrl_list *sc_list, __u32 count, enum nvme_print_flags flags) { - const struct nvme_secondary_ctrl *sc_entry = - &sc_list->sc_entry[0]; - static const char * const state_desc[] = { "Offline", "Online" }; __u16 num = sc_list->num; __u32 entries = min(num, count); - int i; nvme_print(secondary_ctrl_list, flags, sc_list, entries); if (flags & BINARY) return d_raw((unsigned char *)sc_list, sizeof(*sc_list)); - - printf("Identify Secondary Controller List:\n"); - printf(" NUMID : Number of Identifiers : %d\n", num); - - for (i = 0; i < entries; i++) { - printf(" SCEntry[%-3d]:\n", i); - printf("................\n"); - printf(" SCID : Secondary Controller Identifier : 0x%.04x\n", - le16_to_cpu(sc_entry[i].scid)); - printf(" PCID : Primary Controller Identifier : 0x%.04x\n", - le16_to_cpu(sc_entry[i].pcid)); - printf(" SCS : Secondary Controller State : 0x%.04x (%s)\n", - sc_entry[i].scs, - state_desc[sc_entry[i].scs & 0x1]); - printf(" VFN : Virtual Function Number : 0x%.04x\n", - le16_to_cpu(sc_entry[i].vfn)); - printf(" NVQ : Num VQ Flex Resources Assigned : 0x%.04x\n", - le16_to_cpu(sc_entry[i].nvq)); - printf(" NVI : Num VI Flex Resources Assigned : 0x%.04x\n", - le16_to_cpu(sc_entry[i].nvi)); - } } void nvme_show_id_ns_granularity_list(const struct nvme_id_ns_granularity_list *glist, enum nvme_print_flags flags) { - int i; - nvme_print(id_ns_granularity_list, flags, glist); if (flags & BINARY) return d_raw((unsigned char *)glist, sizeof(*glist)); - - printf("Identify Namespace Granularity List:\n"); - printf(" ATTR : Namespace Granularity Attributes: 0x%x\n", - glist->attributes); - printf(" NUMD : Number of Descriptors : %d\n", - glist->num_descriptors); - - /* Number of Descriptors is a 0's based value */ - for (i = 0; i <= glist->num_descriptors; i++) { - printf("\n Entry[%2d] :\n", i); - printf("................\n"); - printf(" NSG : Namespace Size Granularity : 0x%"PRIx64"\n", - le64_to_cpu(glist->entry[i].nszegran)); - printf(" NCG : Namespace Capacity Granularity : 0x%"PRIx64"\n", - le64_to_cpu(glist->entry[i].ncapgran)); - } } void nvme_show_id_uuid_list(const struct nvme_id_uuid_list *uuid_list, enum nvme_print_flags flags) { - int i, human = flags & VERBOSE; - nvme_print(id_uuid_list, flags, uuid_list); if (flags & BINARY) return d_raw((unsigned char *)uuid_list, sizeof(*uuid_list)); - - /* The 0th entry is reserved */ - printf("NVME Identify UUID:\n"); - for (i = 0; i < NVME_ID_UUID_LIST_MAX; i++) { - __u8 uuid[NVME_UUID_LEN]; - char *association = ""; - uint8_t identifier_association = uuid_list->entry[i].header & 0x3; - /* The list is terminated by a zero UUID value */ - if (memcmp(uuid_list->entry[i].uuid, zero_uuid, NVME_UUID_LEN) == 0) - break; - memcpy(&uuid, uuid_list->entry[i].uuid, NVME_UUID_LEN); - if (human) { - switch (identifier_association) { - case 0x0: - association = "No association reported"; - break; - case 0x1: - association = "associated with PCI Vendor ID"; - break; - case 0x2: - association = "associated with PCI Subsystem Vendor ID"; - break; - default: - association = "Reserved"; - break; - } - } - printf(" Entry[%3d]\n", i+1); - printf(".................\n"); - printf("association : 0x%x %s\n", identifier_association, association); - printf("UUID : %s", util_uuid_to_string(uuid)); - if (memcmp(uuid_list->entry[i].uuid, invalid_uuid, - sizeof(zero_uuid)) == 0) - printf(" (Invalid UUID)"); - printf("\n.................\n"); - } } void nvme_show_id_domain_list(struct nvme_id_domain_list *id_dom, enum nvme_print_flags flags) { - int i; - nvme_print(id_domain_list, flags, id_dom); if (flags & BINARY) return d_raw((unsigned char *)id_dom, sizeof(*id_dom)); - - printf("Number of Domain Entries: %u\n", id_dom->num); - for (i = 0; i < id_dom->num; i++) { - printf("Domain Id for Attr Entry[%u]: %u\n", i, - le16_to_cpu(id_dom->domain_attr[i].dom_id)); - printf("Domain Capacity for Attr Entry[%u]: %s\n", i, - uint128_t_to_l10n_string( - le128_to_cpu(id_dom->domain_attr[i].dom_cap))); - printf("Unallocated Domain Capacity for Attr Entry[%u]: %s\n", i, - uint128_t_to_l10n_string( - le128_to_cpu(id_dom->domain_attr[i].unalloc_dom_cap))); - printf("Max Endurance Group Domain Capacity for Attr Entry[%u]: %s\n", i, - uint128_t_to_l10n_string( - le128_to_cpu(id_dom->domain_attr[i].max_egrp_dom_cap))); - } } void nvme_show_endurance_group_list(struct nvme_id_endurance_group_list *endgrp_list, enum nvme_print_flags flags) { - int i; - __u16 num = le16_to_cpu(endgrp_list->num); - nvme_print(endurance_group_list, flags, endgrp_list); - - - printf("num of endurance group ids: %u\n", num); - for (i = 0; i < min(num, 2047); i++) { - printf("[%4u]:%#x\n", i, le16_to_cpu(endgrp_list->identifier[i])); - } } void nvme_show_id_iocs(struct nvme_id_iocs *iocs, enum nvme_print_flags flags) { - __u16 i; - nvme_print(id_iocs, flags, iocs); - - for (i = 0; i < 512; i++) - if (iocs->iocsc[i]) - printf("I/O Command Set Combination[%u]:%"PRIx64"\n", i, - (uint64_t)le64_to_cpu(iocs->iocsc[i])); } const char *nvme_trtype_to_string(__u8 trtype) @@ -3827,271 +721,45 @@ const char *nvme_trtype_to_string(__u8 trtype) void nvme_show_error_log(struct nvme_error_log_page *err_log, int entries, const char *devname, enum nvme_print_flags flags) { - int i; - nvme_print(error_log, flags, err_log, entries, devname); if (flags & BINARY) return d_raw((unsigned char *)err_log, entries * sizeof(*err_log)); - - printf("Error Log Entries for device:%s entries:%d\n", devname, - entries); - printf(".................\n"); - for (i = 0; i < entries; i++) { - __u16 status = le16_to_cpu(err_log[i].status_field) >> 0x1; - - printf(" Entry[%2d] \n", i); - printf(".................\n"); - printf("error_count : %"PRIu64"\n", - le64_to_cpu(err_log[i].error_count)); - printf("sqid : %d\n", err_log[i].sqid); - printf("cmdid : %#x\n", err_log[i].cmdid); - printf("status_field : %#x(%s)\n", status, - nvme_status_to_string(status, false)); - printf("phase_tag : %#x\n", - le16_to_cpu(err_log[i].status_field & 0x1)); - printf("parm_err_loc : %#x\n", - err_log[i].parm_error_location); - printf("lba : %#"PRIx64"\n", - le64_to_cpu(err_log[i].lba)); - printf("nsid : %#x\n", err_log[i].nsid); - printf("vs : %d\n", err_log[i].vs); - printf("trtype : %s\n", - nvme_trtype_to_string(err_log[i].trtype)); - printf("csi : %d\n", err_log[i].csi); - printf("opcode : %#x\n", err_log[i].opcode); - printf("cs : %#"PRIx64"\n", - le64_to_cpu(err_log[i].cs)); - printf("trtype_spec_info: %#x\n", err_log[i].trtype_spec_info); - printf("log_page_version: %d\n", err_log[i].log_page_version); - printf(".................\n"); - } } void nvme_show_resv_report(struct nvme_resv_status *status, int bytes, bool eds, enum nvme_print_flags flags) { - int i, j, regctl, entries; - nvme_print(resv_report, flags, status, bytes, eds); if (flags & BINARY) return d_raw((unsigned char *)status, bytes); - - regctl = status->regctl[0] | (status->regctl[1] << 8); - - printf("\nNVME Reservation status:\n\n"); - printf("gen : %u\n", le32_to_cpu(status->gen)); - printf("rtype : %d\n", status->rtype); - printf("regctl : %d\n", regctl); - printf("ptpls : %d\n", status->ptpls); - - /* check Extended Data Structure bit */ - if (!eds) { - /* - * if status buffer was too small, don't loop past the end of - * the buffer - */ - entries = (bytes - 24) / 24; - if (entries < regctl) - regctl = entries; - - for (i = 0; i < regctl; i++) { - printf("regctl[%d] :\n", i); - printf(" cntlid : %x\n", - le16_to_cpu(status->regctl_ds[i].cntlid)); - printf(" rcsts : %x\n", - status->regctl_ds[i].rcsts); - printf(" hostid : %"PRIx64"\n", - le64_to_cpu(status->regctl_ds[i].hostid)); - printf(" rkey : %"PRIx64"\n", - le64_to_cpu(status->regctl_ds[i].rkey)); - } - } else { - /* if status buffer was too small, don't loop past the end of the buffer */ - entries = (bytes - 64) / 64; - if (entries < regctl) - regctl = entries; - - for (i = 0; i < regctl; i++) { - printf("regctlext[%d] :\n", i); - printf(" cntlid : %x\n", - le16_to_cpu(status->regctl_eds[i].cntlid)); - printf(" rcsts : %x\n", - status->regctl_eds[i].rcsts); - printf(" rkey : %"PRIx64"\n", - le64_to_cpu(status->regctl_eds[i].rkey)); - printf(" hostid : "); - for (j = 0; j < 16; j++) - printf("%02x", - status->regctl_eds[i].hostid[j]); - printf("\n"); - } - } - printf("\n"); } void nvme_show_fw_log(struct nvme_firmware_slot *fw_log, const char *devname, enum nvme_print_flags flags) { - int i; - __le64 *frs; - nvme_print(fw_log, flags, fw_log, devname); if (flags & BINARY) return d_raw((unsigned char *)fw_log, sizeof(*fw_log)); - - printf("Firmware Log for device:%s\n", devname); - printf("afi : %#x\n", fw_log->afi); - for (i = 0; i < 7; i++) { - if (fw_log->frs[i][0]) { - frs = (__le64 *)&fw_log->frs[i]; - printf("frs%d : %#016"PRIx64" (%s)\n", i + 1, - le64_to_cpu(*frs), - util_fw_to_string(fw_log->frs[i])); - } - } } void nvme_show_changed_ns_list_log(struct nvme_ns_list *log, const char *devname, enum nvme_print_flags flags) { - __u32 nsid; - int i; - nvme_print(ns_list_log, flags, log, devname); if (flags & BINARY) return d_raw((unsigned char *)log, sizeof(*log)); - - if (log->ns[0] != cpu_to_le32(NVME_NSID_ALL)) { - for (i = 0; i < NVME_ID_NS_LIST_MAX; i++) { - nsid = le32_to_cpu(log->ns[i]); - if (nsid == 0) - break; - - printf("[%4u]:%#x\n", i, nsid); - } - } else - printf("more than %d ns changed\n", - NVME_ID_NS_LIST_MAX); -} - -static void nvme_show_effects_log_human(FILE *stream, __u32 effect) -{ - const char *set = "+"; - const char *clr = "-"; - - fprintf(stream, " CSUPP+"); - fprintf(stream, " LBCC%s", (effect & NVME_CMD_EFFECTS_LBCC) ? set : clr); - fprintf(stream, " NCC%s", (effect & NVME_CMD_EFFECTS_NCC) ? set : clr); - fprintf(stream, " NIC%s", (effect & NVME_CMD_EFFECTS_NIC) ? set : clr); - fprintf(stream, " CCC%s", (effect & NVME_CMD_EFFECTS_CCC) ? set : clr); - fprintf(stream, " USS%s", (effect & NVME_CMD_EFFECTS_UUID_SEL) ? set : clr); - - if ((effect & NVME_CMD_EFFECTS_CSE_MASK) >> 16 == 0) - fprintf(stream, " No command restriction\n"); - else if ((effect & NVME_CMD_EFFECTS_CSE_MASK) >> 16 == 1) - fprintf(stream, " No other command for same namespace\n"); - else if ((effect & NVME_CMD_EFFECTS_CSE_MASK) >> 16 == 2) - fprintf(stream, " No other command for any namespace\n"); - else - fprintf(stream, " Reserved CSE\n"); -} - -void nvme_print_effects_entry(FILE* stream, int admin, int index, __le32 entry, unsigned int human) { - __u32 effect; - char *format_string; - - format_string = admin ? "ACS%-6d[%-32s] %08x" : "IOCS%-5d[%-32s] %08x"; - - effect = le32_to_cpu(entry); - if (effect & NVME_CMD_EFFECTS_CSUPP) { - fprintf(stream, format_string, index, nvme_cmd_to_string(admin, index), - effect); - if (human) - nvme_show_effects_log_human(stream, effect); - else - fprintf(stream, "\n"); - } -} - -void nvme_print_effects_log_segment(int admin, int a, int b, struct nvme_cmd_effects_log *effects, char* header, int human) { - FILE *stream; - char *stream_location; - size_t stream_size; - - stream = open_memstream(&stream_location, &stream_size); - if (!stream) { - perror("Failed to open stream"); - return; - } - - for (int i = a; i < b; i++) { - if (admin) { - nvme_print_effects_entry(stream, admin, i, effects->acs[i], human); - } - else { - nvme_print_effects_entry(stream, admin, i, - effects->iocs[i], human); - } - } - - fclose(stream); - - if (stream_size && header) { - printf("%s\n", header); - fwrite(stream_location, stream_size, 1, stdout); - printf("\n"); - } - - free(stream_location); -} - -void nvme_print_effects_log_page(enum nvme_csi csi, - struct nvme_cmd_effects_log *effects, - enum nvme_print_flags flags) -{ - int human = flags & VERBOSE; - - switch (csi) { - case NVME_CSI_NVM: - printf("NVM Command Set Log Page\n"); - printf("%-.80s\n", dash); - break; - case NVME_CSI_ZNS: - printf("ZNS Command Set Log Page\n"); - printf("%-.80s\n", dash); - break; - default: - printf("Unknown Command Set Log Page\n"); - printf("%-.80s\n", dash); - break; - } - - nvme_print_effects_log_segment(1, 0, 0xbf, effects, "Admin Commands", human); - nvme_print_effects_log_segment(1, 0xc0, 0xff, effects, "Vendor Specific Admin Commands", human); - nvme_print_effects_log_segment(0, 0, 0x80, effects, "I/O Commands", human); - nvme_print_effects_log_segment(0, 0x80, 0x100, effects, "Vendor Specific I/O Commands", human); } void nvme_print_effects_log_pages(struct list_head *list, enum nvme_print_flags flags) { nvme_print(effects_log_list, flags, list); - - nvme_effects_log_node_t *node; - list_for_each(list, node, node) { - if (flags & BINARY) { - d_raw((unsigned char *)&node->effects, sizeof(node->effects)); - } - else { - nvme_print_effects_log_page(node->csi, &node->effects, flags); - } - } } const char *nvme_log_to_string(__u8 lid) @@ -4123,39 +791,13 @@ const char *nvme_log_to_string(__u8 lid) } } -static void nvme_show_support_log_human(__u32 support, __u8 lid) -{ - const char *set = "supported"; - const char *clr = "not supported"; - - printf(" LSUPP is %s\n", (support & 0x1) ? set : clr); - printf(" IOS is %s\n", ((support >> 0x1) & 0x1) ? set : clr); - if (lid == NVME_LOG_LID_PERSISTENT_EVENT) { - printf(" Establish Context and Read 512 Bytes of Header is %s\n", - ((support >> 0x16) & 0x1) ? set : clr); - } -} - void nvme_show_supported_log(struct nvme_supported_log_pages *support_log, const char *devname, enum nvme_print_flags flags) { - int lid, human = flags & VERBOSE; - __u32 support = 0; - nvme_print(supported_log_pages, flags, support_log, devname); if (flags & BINARY) return d_raw((unsigned char *)support_log, sizeof(*support_log)); - - printf("Support Log Pages Details for %s:\n", devname); - for (lid = 0; lid < 256; lid++) { - support = le32_to_cpu(support_log->lid_support[lid]); - if (support & 0x1) { - printf("LID 0x%x - %s\n", lid, nvme_log_to_string(lid)); - if (human) - nvme_show_support_log_human(support, lid); - } - } } void nvme_show_endurance_log(struct nvme_endurance_group_log *endurance_log, @@ -4167,338 +809,42 @@ void nvme_show_endurance_log(struct nvme_endurance_group_log *endurance_log, if (flags & BINARY) return d_raw((unsigned char *)endurance_log, sizeof(*endurance_log)); - - printf("Endurance Group Log for NVME device:%s Group ID:%x\n", devname, - group_id); - printf("critical warning : %u\n", - endurance_log->critical_warning); - printf("avl_spare : %u\n", endurance_log->avl_spare); - printf("avl_spare_threshold : %u\n", - endurance_log->avl_spare_threshold); - printf("percent_used : %u%%\n", endurance_log->percent_used); - printf("endurance_estimate : %s\n", - uint128_t_to_l10n_string( - le128_to_cpu(endurance_log->endurance_estimate))); - printf("data_units_read : %s\n", - uint128_t_to_l10n_string( - le128_to_cpu(endurance_log->data_units_read))); - printf("data_units_written : %s\n", - uint128_t_to_l10n_string( - le128_to_cpu(endurance_log->data_units_written))); - printf("media_units_written : %s\n", - uint128_t_to_l10n_string( - le128_to_cpu(endurance_log->media_units_written))); - printf("host_read_cmds : %s\n", - uint128_t_to_l10n_string( - le128_to_cpu(endurance_log->host_read_cmds))); - printf("host_write_cmds : %s\n", - uint128_t_to_l10n_string( - le128_to_cpu(endurance_log->host_write_cmds))); - printf("media_data_integrity_err: %s\n", - uint128_t_to_l10n_string( - le128_to_cpu(endurance_log->media_data_integrity_err))); - printf("num_err_info_log_entries: %s\n", - uint128_t_to_l10n_string( - le128_to_cpu(endurance_log->num_err_info_log_entries))); } void nvme_show_smart_log(struct nvme_smart_log *smart, unsigned int nsid, const char *devname, enum nvme_print_flags flags) { - __u16 temperature = smart->temperature[1] << 8 | smart->temperature[0]; - int i; - bool human = flags & VERBOSE; - nvme_print(smart_log, flags, smart, nsid, devname); if (flags & BINARY) return d_raw((unsigned char *)smart, sizeof(*smart)); - - printf("Smart Log for NVME device:%s namespace-id:%x\n", devname, nsid); - printf("critical_warning : %#x\n", - smart->critical_warning); - - if (human) { - printf(" Available Spare[0] : %d\n", smart->critical_warning & 0x01); - printf(" Temp. Threshold[1] : %d\n", (smart->critical_warning & 0x02) >> 1); - printf(" NVM subsystem Reliability[2] : %d\n", (smart->critical_warning & 0x04) >> 2); - printf(" Read-only[3] : %d\n", (smart->critical_warning & 0x08) >> 3); - printf(" Volatile mem. backup failed[4] : %d\n", (smart->critical_warning & 0x10) >> 4); - printf(" Persistent Mem. RO[5] : %d\n", (smart->critical_warning & 0x20) >> 5); - } - - printf("temperature : %ld °C (%u K)\n", - kelvin_to_celsius(temperature), temperature); - printf("available_spare : %u%%\n", - smart->avail_spare); - printf("available_spare_threshold : %u%%\n", - smart->spare_thresh); - printf("percentage_used : %u%%\n", - smart->percent_used); - printf("endurance group critical warning summary: %#x\n", - smart->endu_grp_crit_warn_sumry); - printf("Data Units Read : %s (%s)\n", - uint128_t_to_l10n_string(le128_to_cpu(smart->data_units_read)), - uint128_t_to_si_string(le128_to_cpu(smart->data_units_read), - 1000 * 512)); - printf("Data Units Written : %s (%s)\n", - uint128_t_to_l10n_string(le128_to_cpu(smart->data_units_written)), - uint128_t_to_si_string(le128_to_cpu(smart->data_units_written), - 1000 * 512)); - printf("host_read_commands : %s\n", - uint128_t_to_l10n_string(le128_to_cpu(smart->host_reads))); - printf("host_write_commands : %s\n", - uint128_t_to_l10n_string(le128_to_cpu(smart->host_writes))); - printf("controller_busy_time : %s\n", - uint128_t_to_l10n_string(le128_to_cpu(smart->ctrl_busy_time))); - printf("power_cycles : %s\n", - uint128_t_to_l10n_string(le128_to_cpu(smart->power_cycles))); - printf("power_on_hours : %s\n", - uint128_t_to_l10n_string(le128_to_cpu(smart->power_on_hours))); - printf("unsafe_shutdowns : %s\n", - uint128_t_to_l10n_string(le128_to_cpu(smart->unsafe_shutdowns))); - printf("media_errors : %s\n", - uint128_t_to_l10n_string(le128_to_cpu(smart->media_errors))); - printf("num_err_log_entries : %s\n", - uint128_t_to_l10n_string(le128_to_cpu(smart->num_err_log_entries))); - printf("Warning Temperature Time : %u\n", - le32_to_cpu(smart->warning_temp_time)); - printf("Critical Composite Temperature Time : %u\n", - le32_to_cpu(smart->critical_comp_time)); - for (i = 0; i < 8; i++) { - __s32 temp = le16_to_cpu(smart->temp_sensor[i]); - - if (temp == 0) - continue; - printf("Temperature Sensor %d : %ld °C (%u K)\n", - i + 1, kelvin_to_celsius(temp), temp); - } - printf("Thermal Management T1 Trans Count : %u\n", - le32_to_cpu(smart->thm_temp1_trans_count)); - printf("Thermal Management T2 Trans Count : %u\n", - le32_to_cpu(smart->thm_temp2_trans_count)); - printf("Thermal Management T1 Total Time : %u\n", - le32_to_cpu(smart->thm_temp1_total_time)); - printf("Thermal Management T2 Total Time : %u\n", - le32_to_cpu(smart->thm_temp2_total_time)); } void nvme_show_ana_log(struct nvme_ana_log *ana_log, const char *devname, size_t len, enum nvme_print_flags flags) { - int offset = sizeof(struct nvme_ana_log); - struct nvme_ana_log *hdr = ana_log; - struct nvme_ana_group_desc *desc; - size_t nsid_buf_size; - void *base = ana_log; - __u32 nr_nsids; - int i, j; - nvme_print(ana_log, flags, ana_log, devname, len); if (flags & BINARY) return d_raw((unsigned char *)ana_log, len); - - printf("Asymmetric Namespace Access Log for NVMe device: %s\n", - devname); - printf("ANA LOG HEADER :-\n"); - printf("chgcnt : %"PRIu64"\n", - le64_to_cpu(hdr->chgcnt)); - printf("ngrps : %u\n", le16_to_cpu(hdr->ngrps)); - printf("ANA Log Desc :-\n"); - - for (i = 0; i < le16_to_cpu(ana_log->ngrps); i++) { - desc = base + offset; - nr_nsids = le32_to_cpu(desc->nnsids); - nsid_buf_size = nr_nsids * sizeof(__le32); - - offset += sizeof(*desc); - printf("grpid : %u\n", le32_to_cpu(desc->grpid)); - printf("nnsids : %u\n", le32_to_cpu(desc->nnsids)); - printf("chgcnt : %"PRIu64"\n", - le64_to_cpu(desc->chgcnt)); - printf("state : %s\n", - nvme_ana_state_to_string(desc->state)); - for (j = 0; j < le32_to_cpu(desc->nnsids); j++) - printf(" nsid : %u\n", - le32_to_cpu(desc->nsids[j])); - printf("\n"); - offset += nsid_buf_size; - } -} - -static void nvme_show_self_test_result(struct nvme_st_result *res, - enum nvme_print_flags flags) -{ - static const char *const test_res[] = { - "Operation completed without error", - "Operation was aborted by a Device Self-test command", - "Operation was aborted by a Controller Level Reset", - "Operation was aborted due to a removal of a namespace from the namespace inventory", - "Operation was aborted due to the processing of a Format NVM command", - "A fatal error or unknown test error occurred while the controller was executing the"\ - " device self-test operation and the operation did not complete", - "Operation completed with a segment that failed and the segment that failed is not known", - "Operation completed with one or more failed segments and the first segment that failed "\ - "is indicated in the SegmentNumber field", - "Operation was aborted for unknown reason", - "Operation was aborted due to a sanitize operation", - "Reserved", - [NVME_ST_RESULT_NOT_USED] = "Entry not used (does not contain a result)", - }; - __u8 op, code; - - op = res->dsts & NVME_ST_RESULT_MASK; - printf(" Operation Result : %#x", op); - if (flags & VERBOSE) - printf(" %s", (op < ARRAY_SIZE(test_res) && test_res[op]) ? - test_res[op] : test_res[ARRAY_SIZE(test_res) - 1]); - printf("\n"); - if (op == NVME_ST_RESULT_NOT_USED) - return; - - code = res->dsts >> NVME_ST_CODE_SHIFT; - printf(" Self Test Code : %x", code); - - if (flags & VERBOSE) { - switch (code) { - case NVME_ST_CODE_SHORT: - printf(" Short device self-test operation"); - break; - case NVME_ST_CODE_EXTENDED: - printf(" Extended device self-test operation"); - break; - case NVME_ST_CODE_VS: - printf(" Vendor specific"); - break; - default: - printf(" Reserved"); - break; - } - } - printf("\n"); - - if (op == NVME_ST_RESULT_KNOWN_SEG_FAIL) - printf(" Segment Number : %#x\n", res->seg); - - printf(" Valid Diagnostic Information : %#x\n", res->vdi); - printf(" Power on hours (POH) : %#"PRIx64"\n", - (uint64_t)le64_to_cpu(res->poh)); - - if (res->vdi & NVME_ST_VALID_DIAG_INFO_NSID) - printf(" Namespace Identifier : %#x\n", - le32_to_cpu(res->nsid)); - if (res->vdi & NVME_ST_VALID_DIAG_INFO_FLBA) - printf(" Failing LBA : %#"PRIx64"\n", - (uint64_t)le64_to_cpu(res->flba)); - if (res->vdi & NVME_ST_VALID_DIAG_INFO_SCT) - printf(" Status Code Type : %#x\n", res->sct); - if (res->vdi & NVME_ST_VALID_DIAG_INFO_SC) { - printf(" Status Code : %#x", res->sc); - if (flags & VERBOSE) - printf(" %s", nvme_status_to_string( - (res->sct & 7) << 8 | res->sc, false)); - printf("\n"); - } - printf(" Vendor Specific : %#x %#x\n", - res->vs[0], res->vs[1]); } void nvme_show_self_test_log(struct nvme_self_test_log *self_test, __u8 dst_entries, __u32 size, const char *devname, enum nvme_print_flags flags) { - int i; - __u8 num_entries; - nvme_print(self_test_log, flags, self_test, dst_entries, size, devname); if (flags & BINARY) return d_raw((unsigned char *)self_test, size); - - printf("Device Self Test Log for NVME device:%s\n", devname); - printf("Current operation : %#x\n", self_test->current_operation); - printf("Current Completion : %u%%\n", self_test->completion); - num_entries = min(dst_entries, NVME_LOG_ST_MAX_RESULTS); - for (i = 0; i < num_entries; i++) { - printf("Self Test Result[%d]:\n", i); - nvme_show_self_test_result(&self_test->result[i], flags); - } -} - -static void nvme_show_sanitize_log_sprog(__u32 sprog) -{ - double percent; - - percent = (((double)sprog * 100) / 0x10000); - printf("\t(%f%%)\n", percent); -} - -static void nvme_show_sanitize_log_sstat(__u16 status) -{ - const char *str = nvme_sstat_status_to_string(status); - - printf("\t[2:0]\t%s\n", str); - str = "Number of completed passes if most recent operation was overwrite"; - printf("\t[7:3]\t%s:\t%u\n", str, - (status >> NVME_SANITIZE_SSTAT_COMPLETED_PASSES_SHIFT) & - NVME_SANITIZE_SSTAT_COMPLETED_PASSES_MASK); - - printf("\t [8]\t"); - if (status & NVME_SANITIZE_SSTAT_GLOBAL_DATA_ERASED) - str = "Global Data Erased set: no NS LB in the NVM subsystem "\ - "has been written to and no PMR in the NVM subsystem "\ - "has been enabled"; - else - str = "Global Data Erased cleared: a NS LB in the NVM "\ - "subsystem has been written to or a PMR in the NVM "\ - "subsystem has been enabled"; - printf("%s\n", str); -} - -static void nvme_show_estimate_sanitize_time(const char *text, uint32_t value) -{ - printf("%s: %u%s\n", text, value, - value == 0xffffffff ? " (No time period reported)" : ""); } void nvme_show_sanitize_log(struct nvme_sanitize_log_page *sanitize, const char *devname, enum nvme_print_flags flags) { - int human = flags & VERBOSE; - __u16 status = le16_to_cpu(sanitize->sstat) & NVME_SANITIZE_SSTAT_STATUS_MASK; - nvme_print(sanitize_log_page, flags, sanitize, devname); if (flags & BINARY) d_raw((unsigned char *)sanitize, sizeof(*sanitize)); - - printf("Sanitize Progress (SPROG) : %u", - le16_to_cpu(sanitize->sprog)); - - if (human && status == NVME_SANITIZE_SSTAT_STATUS_IN_PROGESS) - nvme_show_sanitize_log_sprog(le16_to_cpu(sanitize->sprog)); - else - printf("\n"); - - printf("Sanitize Status (SSTAT) : %#x\n", - le16_to_cpu(sanitize->sstat)); - if (human) - nvme_show_sanitize_log_sstat(le16_to_cpu(sanitize->sstat)); - - printf("Sanitize Command Dword 10 Information (SCDW10) : %#x\n", - le32_to_cpu(sanitize->scdw10)); - nvme_show_estimate_sanitize_time("Estimated Time For Overwrite ", - le32_to_cpu(sanitize->eto)); - nvme_show_estimate_sanitize_time("Estimated Time For Block Erase ", - le32_to_cpu(sanitize->etbe)); - nvme_show_estimate_sanitize_time("Estimated Time For Crypto Erase ", - le32_to_cpu(sanitize->etce)); - nvme_show_estimate_sanitize_time("Estimated Time For Overwrite (No-Deallocate) ", - le32_to_cpu(sanitize->etond)); - nvme_show_estimate_sanitize_time("Estimated Time For Block Erase (No-Deallocate) ", - le32_to_cpu(sanitize->etbend)); - nvme_show_estimate_sanitize_time("Estimated Time For Crypto Erase (No-Deallocate)", - le32_to_cpu(sanitize->etcend)); } const char *nvme_feature_to_string(enum nvme_features_id feature) @@ -4583,13 +929,6 @@ const char *nvme_select_to_string(int sel) void nvme_show_select_result(__u32 result) { nvme_print(select_result, 0, result); - - if (result & 0x1) - printf(" Feature is saveable\n"); - if (result & 0x2) - printf(" Feature is per-namespace\n"); - if (result & 0x4) - printf(" Feature is changeable\n"); } const char *nvme_feature_lba_type_to_string(__u8 type) @@ -4611,30 +950,9 @@ const char *nvme_feature_lba_type_to_string(__u8 type) void nvme_show_lba_range(struct nvme_lba_range_type *lbrt, int nr_ranges, enum nvme_print_flags flags) { - int i, j; - nvme_print(lba_range, flags, lbrt, nr_ranges); - - for (i = 0; i <= nr_ranges; i++) { - printf("\ttype : %#x - %s\n", lbrt->entry[i].type, - nvme_feature_lba_type_to_string(lbrt->entry[i].type)); - printf("\tattributes : %#x - %s, %s\n", lbrt->entry[i].attributes, - (lbrt->entry[i].attributes & 0x0001) ? - "LBA range may be overwritten" : - "LBA range should not be overwritten", - ((lbrt->entry[i].attributes & 0x0002) >> 1) ? - "LBA range should be hidden from the OS/EFI/BIOS" : - "LBA range should be visible from the OS/EFI/BIOS"); - printf("\tslba : %#"PRIx64"\n", le64_to_cpu(lbrt->entry[i].slba)); - printf("\tnlb : %#"PRIx64"\n", le64_to_cpu(lbrt->entry[i].nlb)); - printf("\tguid : "); - for (j = 0; j < 16; j++) - printf("%02x", lbrt->entry[i].guid[j]); - printf("\n"); - } } - const char *nvme_feature_wl_hints_to_string(__u8 wh) { switch (wh) { @@ -4670,61 +988,6 @@ const char *nvme_feature_temp_sel_to_string(__u8 sel) } } -static void nvme_show_auto_pst(struct nvme_feat_auto_pst *apst) -{ - int i; - __u64 value; - - printf( "\tAuto PST Entries"); - printf("\t.................\n"); - for (i = 0; i < 32; i++) { - value = le64_to_cpu(apst->apst_entry[i]); - - printf("\tEntry[%2d] \n", i); - printf("\t.................\n"); - printf("\tIdle Time Prior to Transition (ITPT): %u ms\n", - (__u32)(value >> NVME_APST_ENTRY_ITPT_SHIFT) & NVME_APST_ENTRY_ITPT_MASK); - printf("\tIdle Transition Power State (ITPS): %u\n", - (__u32)(value >> NVME_APST_ENTRY_ITPS_SHIFT ) & NVME_APST_ENTRY_ITPS_MASK); - printf("\t.................\n"); - } -} - -static void nvme_show_timestamp(struct nvme_timestamp *ts) -{ - struct tm *tm; - char buffer[320]; - time_t timestamp = int48_to_long(ts->timestamp) / 1000; - - tm = localtime(×tamp); - - printf("\tThe timestamp is : %'"PRIu64" (%s)\n", - int48_to_long(ts->timestamp), - strftime(buffer, sizeof(buffer), "%c %Z", tm) ? buffer : "-"); - printf("\t%s\n", (ts->attr & 2) ? - "The Timestamp field was initialized with a "\ - "Timestamp value using a Set Features command." : - "The Timestamp field was initialized "\ - "to ‘0’ by a Controller Level Reset."); - printf("\t%s\n", (ts->attr & 1) ? - "The controller may have stopped counting during vendor specific "\ - "intervals after the Timestamp value was initialized" : - "The controller counted time in milliseconds "\ - "continuously since the Timestamp value was initialized."); -} - -static void nvme_show_host_mem_buffer(struct nvme_host_mem_buf_attrs *hmb) -{ - printf("\tHost Memory Descriptor List Entry Count (HMDLEC): %u\n", - le32_to_cpu(hmb->hmdlec)); - printf("\tHost Memory Descriptor List Address (HMDLAU): 0x%x\n", - le32_to_cpu(hmb->hmdlau)); - printf("\tHost Memory Descriptor List Address (HMDLAL): 0x%x\n", - le32_to_cpu(hmb->hmdlal)); - printf("\tHost Memory Buffer Size (HSIZE): %u\n", - le32_to_cpu(hmb->hsize)); -} - const char *nvme_ns_wp_cfg_to_string(enum nvme_ns_write_protect_cfg state) { switch (state) { @@ -4741,88 +1004,6 @@ const char *nvme_ns_wp_cfg_to_string(enum nvme_ns_write_protect_cfg state) } } -static void nvme_directive_show_fields(__u8 dtype, __u8 doper, - unsigned int result, unsigned char *buf) -{ - __u8 *field = buf; - int count, i; - - switch (dtype) { - case NVME_DIRECTIVE_DTYPE_IDENTIFY: - switch (doper) { - case NVME_DIRECTIVE_RECEIVE_IDENTIFY_DOPER_PARAM: - printf("\tDirective support \n"); - printf("\t\tIdentify Directive : %s\n", - (*field & 0x1) ? "supported":"not supported"); - printf("\t\tStream Directive : %s\n", - (*field & 0x2) ? "supported":"not supported"); - printf("\t\tData Placement Directive : %s\n", - (*field & 0x4) ? "supported":"not supported"); - printf("\tDirective enabled \n"); - printf("\t\tIdentify Directive : %s\n", - (*(field + 32) & 0x1) ? "enabled" : "disabled"); - printf("\t\tStream Directive : %s\n", - (*(field + 32) & 0x2) ? "enabled" : "disabled"); - printf("\t\tData Placement Directive : %s\n", - (*(field + 32) & 0x4) ? "enabled" : "disabled"); - printf("\tDirective Persistent Across Controller Level Resets \n"); - printf("\t\tIdentify Directive : %s\n", - (*(field + 32) & 0x1) ? "enabled" : "disabled"); - printf("\t\tStream Directive : %s\n", - (*(field + 32) & 0x2) ? "enabled" : "disabled"); - printf("\t\tData Placement Directive : %s\n", - (*(field + 32) & 0x4) ? "enabled" : "disabled"); - - break; - default: - fprintf(stderr, - "invalid directive operations for Identify Directives\n"); - } - break; - case NVME_DIRECTIVE_DTYPE_STREAMS: - switch (doper) { - case NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_PARAM: - printf("\tMax Streams Limit (MSL): %u\n", - *(__u16 *) field); - printf("\tNVM Subsystem Streams Available (NSSA): %u\n", - *(__u16 *) (field + 2)); - printf("\tNVM Subsystem Streams Open (NSSO): %u\n", - *(__u16 *) (field + 4)); - printf("\tNVM Subsystem Stream Capability (NSSC): %u\n", - *(__u16 *) (field + 6)); - printf("\tStream Write Size (in unit of LB size) (SWS): %u\n", - *(__u32 *) (field + 16)); - printf("\tStream Granularity Size (in unit of SWS) (SGS): %u\n", - *(__u16 *) (field + 20)); - printf("\tNamespace Streams Allocated (NSA): %u\n", - *(__u16 *) (field + 22)); - printf("\tNamespace Streams Open (NSO): %u\n", - *(__u16 *) (field + 24)); - break; - case NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_STATUS: - count = *(__u16 *) field; - printf("\tOpen Stream Count : %u\n", *(__u16 *) field); - for ( i = 0; i < count; i++ ) { - printf("\tStream Identifier %.6u : %u\n", i + 1, - *(__u16 *) (field + ((i + 1) * 2))); - } - break; - case NVME_DIRECTIVE_RECEIVE_STREAMS_DOPER_RESOURCE: - printf("\tNamespace Streams Allocated (NSA): %u\n", - result & 0xffff); - break; - default: - fprintf(stderr, - "invalid directive operations for Streams Directives\n"); - } - break; - default: - fprintf(stderr, "invalid directive type\n"); - break; - } - return; -} - void nvme_directive_show(__u8 type, __u8 oper, __u16 spec, __u32 nsid, __u32 result, void *buf, __u32 len, enum nvme_print_flags flags) { @@ -4834,13 +1015,6 @@ void nvme_directive_show(__u8 type, __u8 oper, __u16 spec, __u32 nsid, __u32 res return d_raw(buf, len); return; } - - printf("dir-receive: type:%#x operation:%#x spec:%#x nsid:%#x result:%#x\n", - type, oper, spec, nsid, result); - if (flags & VERBOSE) - nvme_directive_show_fields(type, oper, result, buf); - else if (buf) - d(buf, len, 16, 1); } const char *nvme_plm_window_to_string(__u32 plm) @@ -4863,14 +1037,6 @@ void nvme_show_lba_status_info(__u32 result) printf("\tLBA Status Information Report Interval (LSIRI): %u\n", result & 0xffff); } -static void nvme_show_plm_config(struct nvme_plm_config *plmcfg) -{ - printf("\tEnable Event :%04x\n", le16_to_cpu(plmcfg->ee)); - printf("\tDTWIN Reads Threshold :%"PRIu64"\n", le64_to_cpu(plmcfg->dtwinrt)); - printf("\tDTWIN Writes Threshold:%"PRIu64"\n", le64_to_cpu(plmcfg->dtwinwt)); - printf("\tDTWIN Time Threshold :%"PRIu64"\n", le64_to_cpu(plmcfg->dtwintt)); -} - const char *nvme_host_metadata_type_to_string(enum nvme_features_id fid, __u8 type) { @@ -4931,257 +1097,18 @@ const char *nvme_host_metadata_type_to_string(enum nvme_features_id fid, } } -static void nvme_show_host_metadata(enum nvme_features_id fid, - struct nvme_host_metadata *data) -{ - struct nvme_metadata_element_desc *desc = &data->descs[0]; - int i; - char val[4096]; - __u16 len; - - printf("\tNum Metadata Element Descriptors: %d\n", data->ndesc); - for (i = 0; i < data->ndesc; i++) { - len = le16_to_cpu(desc->len); - strncpy(val, (char *)desc->val, min(sizeof(val) - 1, len)); - - printf("\tElement[%-3d]:\n", i); - printf("\t\tType : 0x%02x (%s)\n", desc->type, - nvme_host_metadata_type_to_string(fid, desc->type)); - printf("\t\tRevision : %d\n", desc->rev); - printf("\t\tLength : %d\n", len); - printf("\t\tValue : %s\n", val); - - desc = (struct nvme_metadata_element_desc *) - &desc->val[desc->len]; - } -} - void nvme_feature_show_fields(enum nvme_features_id fid, unsigned int result, unsigned char *buf) { - __u8 field; - uint64_t ull; - nvme_print(show_feature_fields, 0, fid, result, buf); - - switch (fid) { - case NVME_FEAT_FID_ARBITRATION: - printf("\tHigh Priority Weight (HPW): %u\n", ((result & 0xff000000) >> 24) + 1); - printf("\tMedium Priority Weight (MPW): %u\n", ((result & 0x00ff0000) >> 16) + 1); - printf("\tLow Priority Weight (LPW): %u\n", ((result & 0x0000ff00) >> 8) + 1); - printf("\tArbitration Burst (AB): "); - if ((result & 0x00000007) == 7) - printf("No limit\n"); - else - printf("%u\n", 1 << (result & 0x00000007)); - break; - case NVME_FEAT_FID_POWER_MGMT: - field = (result & 0x000000E0) >> 5; - printf("\tWorkload Hint (WH): %u - %s\n", field, nvme_feature_wl_hints_to_string(field)); - printf("\tPower State (PS): %u\n", result & 0x0000001f); - break; - case NVME_FEAT_FID_LBA_RANGE: - field = result & 0x0000003f; - printf("\tNumber of LBA Ranges (NUM): %u\n", field + 1); - if (buf) - nvme_show_lba_range((struct nvme_lba_range_type *)buf, field, 0); - break; - case NVME_FEAT_FID_TEMP_THRESH: - field = (result & 0x00300000) >> 20; - printf("\tThreshold Type Select (THSEL): %u - %s\n", field, - nvme_feature_temp_type_to_string(field)); - field = (result & 0x000f0000) >> 16; - printf("\tThreshold Temperature Select (TMPSEL): %u - %s\n", - field, nvme_feature_temp_sel_to_string(field)); - printf("\tTemperature Threshold (TMPTH): %ld °C (%u K)\n", - kelvin_to_celsius(result & 0x0000ffff), result & 0x0000ffff); - break; - case NVME_FEAT_FID_ERR_RECOVERY: - printf("\tDeallocated or Unwritten Logical Block Error Enable (DULBE): %s\n", - ((result & 0x00010000) >> 16) ? "Enabled":"Disabled"); - printf("\tTime Limited Error Recovery (TLER): %u ms\n", - (result & 0x0000ffff) * 100); - break; - case NVME_FEAT_FID_VOLATILE_WC: - printf("\tVolatile Write Cache Enable (WCE): %s\n", (result & 0x00000001) ? "Enabled":"Disabled"); - break; - case NVME_FEAT_FID_NUM_QUEUES: - printf("\tNumber of IO Completion Queues Allocated (NCQA): %u\n", ((result & 0xffff0000) >> 16) + 1); - printf("\tNumber of IO Submission Queues Allocated (NSQA): %u\n", (result & 0x0000ffff) + 1); - break; - case NVME_FEAT_FID_IRQ_COALESCE: - printf("\tAggregation Time (TIME): %u usec\n", ((result & 0x0000ff00) >> 8) * 100); - printf("\tAggregation Threshold (THR): %u\n", (result & 0x000000ff) + 1); - break; - case NVME_FEAT_FID_IRQ_CONFIG: - printf("\tCoalescing Disable (CD): %s\n", ((result & 0x00010000) >> 16) ? "True":"False"); - printf("\tInterrupt Vector (IV): %u\n", result & 0x0000ffff); - break; - case NVME_FEAT_FID_WRITE_ATOMIC: - printf("\tDisable Normal (DN): %s\n", (result & 0x00000001) ? "True":"False"); - break; - case NVME_FEAT_FID_ASYNC_EVENT: - printf("\tDiscovery Log Page Change Notices : %s\n", - ((result & 0x80000000) >> 31) ? "Send async event":"Do not send async event"); - printf("\tEndurance Group Event Aggregate Log Change Notices : %s\n", - ((result & 0x00004000) >> 14) ? "Send async event":"Do not send async event"); - printf("\tLBA Status Information Notices : %s\n", - ((result & 0x00002000) >> 13) ? "Send async event":"Do not send async event"); - printf("\tPredictable Latency Event Aggregate Log Change Notices : %s\n", - ((result & 0x00001000) >> 12) ? "Send async event":"Do not send async event"); - printf("\tAsymmetric Namespace Access Change Notices : %s\n", - ((result & 0x00000800) >> 11) ? "Send async event":"Do not send async event"); - printf("\tTelemetry Log Notices : %s\n", - ((result & 0x00000400) >> 10) ? "Send async event":"Do not send async event"); - printf("\tFirmware Activation Notices : %s\n", - ((result & 0x00000200) >> 9) ? "Send async event":"Do not send async event"); - printf("\tNamespace Attribute Notices : %s\n", - ((result & 0x00000100) >> 8) ? "Send async event":"Do not send async event"); - printf("\tSMART / Health Critical Warnings : %s\n", - (result & 0x000000ff) ? "Send async event":"Do not send async event"); - break; - case NVME_FEAT_FID_AUTO_PST: - printf("\tAutonomous Power State Transition Enable (APSTE): %s\n", - (result & 0x00000001) ? "Enabled":"Disabled"); - if (buf) - nvme_show_auto_pst((struct nvme_feat_auto_pst *)buf); - break; - case NVME_FEAT_FID_HOST_MEM_BUF: - printf("\tEnable Host Memory (EHM): %s\n", (result & 0x00000001) ? "Enabled":"Disabled"); - if (buf) - nvme_show_host_mem_buffer((struct nvme_host_mem_buf_attrs *)buf); - break; - case NVME_FEAT_FID_TIMESTAMP: - if (buf) - nvme_show_timestamp((struct nvme_timestamp *)buf); - break; - case NVME_FEAT_FID_KATO: - printf("\tKeep Alive Timeout (KATO) in milliseconds: %u\n", result); - break; - case NVME_FEAT_FID_HCTM: - printf("\tThermal Management Temperature 1 (TMT1) : %u K (%ld °C)\n", - result >> 16, kelvin_to_celsius(result >> 16)); - printf("\tThermal Management Temperature 2 (TMT2) : %u K (%ld °C)\n", - result & 0x0000ffff, kelvin_to_celsius(result & 0x0000ffff)); - break; - case NVME_FEAT_FID_NOPSC: - printf("\tNon-Operational Power State Permissive Mode Enable (NOPPME): %s\n", - (result & 1) ? "True" : "False"); - break; - case NVME_FEAT_FID_RRL: - printf("\tRead Recovery Level (RRL): %u\n", result & 0xf); - break; - case NVME_FEAT_FID_PLM_CONFIG: - printf("\tPredictable Latency Window Enabled: %s\n", result & 0x1 ? "True":"False"); - if (buf) - nvme_show_plm_config((struct nvme_plm_config *)buf); - break; - case NVME_FEAT_FID_PLM_WINDOW: - printf("\tWindow Select: %s", nvme_plm_window_to_string(result)); - break; - case NVME_FEAT_FID_LBA_STS_INTERVAL: - nvme_show_lba_status_info(result); - break; - case NVME_FEAT_FID_HOST_BEHAVIOR: - if (buf) - printf("\tHost Behavior Support: %s\n", (buf[0] & 0x1) ? "True" : "False"); - break; - case NVME_FEAT_FID_SANITIZE: - printf("\tNo-Deallocate Response Mode (NODRM) : %u\n", result & 0x1); - break; - case NVME_FEAT_FID_ENDURANCE_EVT_CFG: - printf("\tEndurance Group Identifier (ENDGID): %u\n", result & 0xffff); - printf("\tEndurance Group Critical Warnings : %u\n", (result >> 16) & 0xff); - break; - case NVME_FEAT_FID_IOCS_PROFILE: - printf("\tI/O Command Set Profile: %s\n", result & 0x1 ? "True":"False"); - break; - case NVME_FEAT_FID_SPINUP_CONTROL: - printf("\tSpinup control feature Enabled: %s\n", (result & 1) ? "True" : "False"); - break; - case NVME_FEAT_FID_ENH_CTRL_METADATA: - case NVME_FEAT_FID_CTRL_METADATA: - case NVME_FEAT_FID_NS_METADATA: - if (buf) - nvme_show_host_metadata(fid, (struct nvme_host_metadata *)buf); - break; - case NVME_FEAT_FID_SW_PROGRESS: - printf("\tPre-boot Software Load Count (PBSLC): %u\n", result & 0x000000ff); - break; - case NVME_FEAT_FID_HOST_ID: - if (buf) { - ull = buf[7]; ull <<= 8; ull |= buf[6]; ull <<= 8; ull |= buf[5]; ull <<= 8; - ull |= buf[4]; ull <<= 8; ull |= buf[3]; ull <<= 8; ull |= buf[2]; ull <<= 8; - ull |= buf[1]; ull <<= 8; ull |= buf[0]; - printf("\tHost Identifier (HOSTID): %" PRIu64 "\n", ull); - } - break; - case NVME_FEAT_FID_RESV_MASK: - printf("\tMask Reservation Preempted Notification (RESPRE): %s\n", - ((result & 0x00000008) >> 3) ? "True":"False"); - printf("\tMask Reservation Released Notification (RESREL): %s\n", - ((result & 0x00000004) >> 2) ? "True":"False"); - printf("\tMask Registration Preempted Notification (REGPRE): %s\n", - ((result & 0x00000002) >> 1) ? "True":"False"); - break; - case NVME_FEAT_FID_RESV_PERSIST: - printf("\tPersist Through Power Loss (PTPL): %s\n", (result & 0x00000001) ? "True":"False"); - break; - case NVME_FEAT_FID_WRITE_PROTECT: - printf("\tNamespace Write Protect: %s\n", nvme_ns_wp_cfg_to_string(result)); - break; - case NVME_FEAT_FID_FDP: - printf("\tFlexible Direct Placement Enable (FDPE) : %s\n", - (result & 0x1) ? "Yes" : "No"); - printf("\tFlexible Direct Placement Configuration Index : %u\n", - (result >> 8) & 0xf); - break; - case NVME_FEAT_FID_FDP_EVENTS: - for (unsigned int i = 0; i < result; i++) { - struct nvme_fdp_supported_event_desc *d; - - d = &((struct nvme_fdp_supported_event_desc *)buf)[i]; - - printf("\t%-53s: %sEnabled\n", nvme_fdp_event_to_string(d->evt), - d->evta & 0x1 ? "" : "Not "); - } - default: - break; - } } void nvme_show_lba_status(struct nvme_lba_status *list, unsigned long len, enum nvme_print_flags flags) { - int idx; - nvme_print(lba_status, flags, list, len); if (flags & BINARY) return d_raw((unsigned char *)list, len); - - printf("Number of LBA Status Descriptors(NLSD): %" PRIu32 "\n", - le32_to_cpu(list->nlsd)); - printf("Completion Condition(CMPC): %u\n", list->cmpc); - - switch (list->cmpc) { - case 1: - printf("\tCompleted due to transferring the amount of data"\ - " specified in the MNDW field\n"); - break; - case 2: - printf("\tCompleted due to having performed the action\n"\ - "\tspecified in the Action Type field over the\n"\ - "\tnumber of logical blocks specified in the\n"\ - "\tRange Length field\n"); - break; - } - - for (idx = 0; idx < list->nlsd; idx++) { - struct nvme_lba_status_desc *e = &list->descs[idx]; - printf("{ DSLBA: 0x%016"PRIu64", NLB: 0x%08x, Status: 0x%02x }\n", - le64_to_cpu(e->dslba), le32_to_cpu(e->nlb), - e->status); - } } void nvme_dev_full_path(nvme_ns_t n, char *path, size_t len) @@ -5227,298 +1154,12 @@ void nvme_generic_full_path(nvme_ns_t n, char *path, size_t len) void nvme_show_list_item(nvme_ns_t n) { - char usage[128] = { 0 }, format[128] = { 0 }; - char devname[128] = { 0 }; char genname[128] = { 0 }; - - long long lba = nvme_ns_get_lba_size(n); - double nsze = nvme_ns_get_lba_count(n) * lba; - double nuse = nvme_ns_get_lba_util(n) * lba; - - const char *s_suffix = suffix_si_get(&nsze); - const char *u_suffix = suffix_si_get(&nuse); - const char *l_suffix = suffix_binary_get(&lba); - - snprintf(usage, sizeof(usage), "%6.2f %2sB / %6.2f %2sB", nuse, - u_suffix, nsze, s_suffix); - snprintf(format, sizeof(format), "%3.0f %2sB + %2d B", (double)lba, - l_suffix, nvme_ns_get_meta_size(n)); - - nvme_dev_full_path(n, devname, sizeof(devname)); - nvme_generic_full_path(n, genname, sizeof(genname)); - - printf("%-21s %-21s %-20s %-40s %#-10x %-26s %-16s %-8s\n", - devname, genname, nvme_ns_get_serial(n), - nvme_ns_get_model(n), nvme_ns_get_nsid(n), usage, format, - nvme_ns_get_firmware(n)); -} - -static void nvme_show_simple_list(nvme_root_t r) -{ - nvme_host_t h; - nvme_subsystem_t s; - nvme_ctrl_t c; - nvme_ns_t n; - - printf("%-21s %-21s %-20s %-40s %-10s %-26s %-16s %-8s\n", - "Node", "Generic", "SN", "Model", "Namespace", "Usage", "Format", "FW Rev"); - printf("%-.21s %-.21s %-.20s %-.40s %-.10s %-.26s %-.16s %-.8s\n", - dash, dash, dash, dash, dash, dash, dash, dash); - - nvme_for_each_host(r, h) { - nvme_for_each_subsystem(h, s) { - nvme_subsystem_for_each_ns(s, n) - nvme_show_list_item(n); - - nvme_subsystem_for_each_ctrl(s, c) - nvme_ctrl_for_each_ns(c, n) - nvme_show_list_item(n); - } - } -} - -static void nvme_show_ns_details(nvme_ns_t n) -{ - char usage[128] = { 0 }, format[128] = { 0 }; - char devname[128] = { 0 }, genname[128] = { 0 }; - - long long lba = nvme_ns_get_lba_size(n); - double nsze = nvme_ns_get_lba_count(n) * lba; - double nuse = nvme_ns_get_lba_util(n) * lba; - - const char *s_suffix = suffix_si_get(&nsze); - const char *u_suffix = suffix_si_get(&nuse); - const char *l_suffix = suffix_binary_get(&lba); - - sprintf(usage,"%6.2f %2sB / %6.2f %2sB", nuse, u_suffix, nsze, s_suffix); - sprintf(format,"%3.0f %2sB + %2d B", (double)lba, l_suffix, - nvme_ns_get_meta_size(n)); - - nvme_dev_full_path(n, devname, sizeof(devname)); - nvme_generic_full_path(n, genname, sizeof(genname)); - - printf("%-12s %-12s %#-10x %-26s %-16s ", devname, - genname, nvme_ns_get_nsid(n), usage, format); -} - -static void nvme_show_detailed_list(nvme_root_t r) -{ - nvme_host_t h; - nvme_subsystem_t s; - nvme_ctrl_t c; - nvme_path_t p; - nvme_ns_t n; - - printf("%-16s %-96s %-.16s\n", "Subsystem", "Subsystem-NQN", "Controllers"); - printf("%-.16s %-.96s %-.16s\n", dash, dash, dash); - - nvme_for_each_host(r, h) { - nvme_for_each_subsystem(h, s) { - bool first = true; - printf("%-16s %-96s ", nvme_subsystem_get_name(s), - nvme_subsystem_get_nqn(s)); - - nvme_subsystem_for_each_ctrl(s, c) { - printf("%s%s", first ? "": ", ", - nvme_ctrl_get_name(c)); - first = false; - } - printf("\n"); - } - } - printf("\n"); - - printf("%-8s %-20s %-40s %-8s %-6s %-14s %-12s %-16s\n", "Device", - "SN", "MN", "FR", "TxPort", "Address", "Subsystem", "Namespaces"); - printf("%-.8s %-.20s %-.40s %-.8s %-.6s %-.14s %-.12s %-.16s\n", dash, dash, - dash, dash, dash, dash, dash, dash); - - nvme_for_each_host(r, h) { - nvme_for_each_subsystem(h, s) { - nvme_subsystem_for_each_ctrl(s, c) { - bool first = true; - - printf("%-8s %-20s %-40s %-8s %-6s %-14s %-12s ", - nvme_ctrl_get_name(c), - nvme_ctrl_get_serial(c), - nvme_ctrl_get_model(c), - nvme_ctrl_get_firmware(c), - nvme_ctrl_get_transport(c), - nvme_ctrl_get_address(c), - nvme_subsystem_get_name(s)); - - nvme_ctrl_for_each_ns(c, n) { - printf("%s%s", first ? "": ", ", - nvme_ns_get_name(n)); - first = false; - } - - nvme_ctrl_for_each_path(c, p) { - n = nvme_path_get_ns(p); - if (!n) - continue; - printf("%s%s", first ? "": ", ", - nvme_ns_get_name(n)); - first = false; - } - printf("\n"); - } - } - } - printf("\n"); - - printf("%-12s %-12s %-10s %-26s %-16s %-16s\n", "Device", "Generic", - "NSID", "Usage", "Format", "Controllers"); - printf("%-.12s %-.12s %-.10s %-.26s %-.16s %-.16s\n", dash, dash, dash, - dash, dash, dash); - - nvme_for_each_host(r, h) { - nvme_for_each_subsystem(h, s) { - nvme_subsystem_for_each_ctrl(s, c) { - nvme_ctrl_for_each_ns(c, n) { - nvme_show_ns_details(n); - printf("%s\n", nvme_ctrl_get_name(c)); - } - } - - nvme_subsystem_for_each_ns(s, n) { - bool first = true; - - nvme_show_ns_details(n); - nvme_subsystem_for_each_ctrl(s, c) { - printf("%s%s", first ? "" : ", ", - nvme_ctrl_get_name(c)); - first = false; - } - printf("\n"); - } - } - } + nvme_print(list_item, 0, n); } void nvme_show_list_items(nvme_root_t r, enum nvme_print_flags flags) { - nvme_print(list_items, flags, r); - - if (flags & VERBOSE) - nvme_show_detailed_list(r); - else - nvme_show_simple_list(r); -} - -static bool nvme_is_multipath(nvme_subsystem_t s) -{ - nvme_ns_t n; - nvme_path_t p; - - nvme_subsystem_for_each_ns(s, n) - nvme_namespace_for_each_path(n, p) - return true; - - return false; -} - -static void nvme_show_subsystem_topology_multipath(nvme_subsystem_t s, - enum nvme_cli_topo_ranking ranking) -{ - nvme_ns_t n; - nvme_path_t p; - nvme_ctrl_t c; - - if (ranking == NVME_CLI_TOPO_NAMESPACE) { - nvme_subsystem_for_each_ns(s, n) { - printf(" +- ns %d\n", nvme_ns_get_nsid(n)); - printf(" \\\n"); - - nvme_namespace_for_each_path(n, p) { - c = nvme_path_get_ctrl(p); - - printf(" +- %s %s %s %s %s\n", - nvme_ctrl_get_name(c), - nvme_ctrl_get_transport(c), - nvme_ctrl_get_address(c), - nvme_ctrl_get_state(c), - nvme_path_get_ana_state(p)); - } - } - } else { - /* NVME_CLI_TOPO_CTRL */ - nvme_subsystem_for_each_ctrl(s, c) { - printf(" +- %s %s %s\n", - nvme_ctrl_get_name(c), - nvme_ctrl_get_transport(c), - nvme_ctrl_get_address(c)); - printf(" \\\n"); - - nvme_subsystem_for_each_ns(s, n) { - nvme_namespace_for_each_path(n, p) { - if (nvme_path_get_ctrl(p) != c) - continue; - - printf(" +- ns %d %s %s\n", - nvme_ns_get_nsid(n), - nvme_ctrl_get_state(c), - nvme_path_get_ana_state(p)); - } - } - } - } -} - -static void nvme_show_subsystem_topology(nvme_subsystem_t s, - enum nvme_cli_topo_ranking ranking) -{ - nvme_ctrl_t c; - nvme_ns_t n; - - if (ranking == NVME_CLI_TOPO_NAMESPACE) { - nvme_subsystem_for_each_ctrl(s, c) { - nvme_ctrl_for_each_ns(c, n) { - printf(" +- ns %d\n", nvme_ns_get_nsid(n)); - printf(" \\\n"); - printf(" +- %s %s %s %s\n", - nvme_ctrl_get_name(c), - nvme_ctrl_get_transport(c), - nvme_ctrl_get_address(c), - nvme_ctrl_get_state(c)); - } - } - } else { - /* NVME_CLI_TOPO_CTRL */ - nvme_subsystem_for_each_ctrl(s, c) { - printf(" +- %s %s %s\n", - nvme_ctrl_get_name(c), - nvme_ctrl_get_transport(c), - nvme_ctrl_get_address(c)); - printf(" \\\n"); - nvme_ctrl_for_each_ns(c, n) { - printf(" +- ns %d %s\n", - nvme_ns_get_nsid(n), - nvme_ctrl_get_state(c)); - } - } - } -} - -static void nvme_show_simple_topology(nvme_root_t r, - enum nvme_cli_topo_ranking ranking) -{ - nvme_host_t h; - nvme_subsystem_t s; - - nvme_for_each_host(r, h) { - nvme_for_each_subsystem(h, s) { - - printf("%s - NQN=%s\n", nvme_subsystem_get_name(s), - nvme_subsystem_get_nqn(s)); - printf("\\\n"); - - if (nvme_is_multipath(s)) - nvme_show_subsystem_topology_multipath(s, ranking); - else - nvme_show_subsystem_topology(s, ranking); - } - } } void nvme_show_topology(nvme_root_t r, @@ -5526,8 +1167,6 @@ void nvme_show_topology(nvme_root_t r, enum nvme_print_flags flags) { nvme_print(topology_namespace, flags, r); - - nvme_show_simple_topology(r, ranking); } void nvme_show_message(bool error, const char *msg, ...) @@ -5536,21 +1175,17 @@ void nvme_show_message(bool error, const char *msg, ...) va_list ap; va_start(ap, msg); - if (argconfig_output_format_json(false)) { + if (argconfig_output_format_json(false)) ops = nvme_print_ops(JSON); - if (!ops) - return; + else + ops = nvme_print_ops(0); - if (!ops->show_message) - return; - ops->show_message(error, msg, ap); - va_end(ap); + if (!ops) return; - } - vfprintf(error ? stderr : stdout, msg, ap); - - printf("\n"); + if (!ops->show_message) + return; + ops->show_message(error, msg, ap); va_end(ap); } @@ -5559,62 +1194,17 @@ void nvme_show_perror(const char *msg) { struct print_ops *ops; - if (argconfig_output_format_json(false)) { + if (argconfig_output_format_json(false)) ops = nvme_print_ops(JSON); - if (!ops) - return; + else + ops = nvme_print_ops(0); - if (!ops->show_perror) - return; - ops->show_perror(msg); + if (!ops) return; - } - perror(msg); -} - -static void print_discovery_log(struct nvmf_discovery_log *log, int numrec, - enum nvme_print_flags flags) -{ - int i; - - printf("\nDiscovery Log Number of Records %d, Generation counter %"PRIu64"\n", - numrec, le64_to_cpu(log->genctr)); - - for (i = 0; i < numrec; i++) { - struct nvmf_disc_log_entry *e = &log->entries[i]; - - printf("=====Discovery Log Entry %d======\n", i); - printf("trtype: %s\n", nvmf_trtype_str(e->trtype)); - printf("adrfam: %s\n", - strlen(e->traddr) ? - nvmf_adrfam_str(e->adrfam) : ""); - printf("subtype: %s\n", nvmf_subtype_str(e->subtype)); - printf("treq: %s\n", nvmf_treq_str(e->treq)); - printf("portid: %d\n", le16_to_cpu(e->portid)); - printf("trsvcid: %s\n", e->trsvcid); - printf("subnqn: %s\n", e->subnqn); - printf("traddr: %s\n", e->traddr); - printf("eflags: %s\n", - nvmf_eflags_str(le16_to_cpu(e->eflags))); - - switch (e->trtype) { - case NVMF_TRTYPE_RDMA: - printf("rdma_prtype: %s\n", - nvmf_prtype_str(e->tsas.rdma.prtype)); - printf("rdma_qptype: %s\n", - nvmf_qptype_str(e->tsas.rdma.qptype)); - printf("rdma_cms: %s\n", - nvmf_cms_str(e->tsas.rdma.cms)); - printf("rdma_pkey: 0x%04x\n", - le16_to_cpu(e->tsas.rdma.pkey)); - break; - case NVMF_TRTYPE_TCP: - printf("sectype: %s\n", - nvmf_sectype_str(e->tsas.tcp.sectype)); - break; - } - } + if (!ops->show_perror) + return; + ops->show_perror(msg); } void nvme_show_discovery_log(struct nvmf_discovery_log *log, uint64_t numrec, @@ -5628,18 +1218,9 @@ void nvme_show_discovery_log(struct nvmf_discovery_log *log, uint64_t numrec, numrec * sizeof(struct nvmf_disc_log_entry)); return; } - - print_discovery_log(log, numrec, flags); -} - -static void print_connect_msg(nvme_ctrl_t c, enum nvme_print_flags flags) -{ - printf("device: %s\n", nvme_ctrl_get_name(c)); } void nvme_show_connect_msg(nvme_ctrl_t c, enum nvme_print_flags flags) { nvme_print(connect_msg, flags, c); - - print_connect_msg(c, flags); } diff --git a/nvme-print.h b/nvme-print.h index c75cee59..bca47c02 100644 --- a/nvme-print.h +++ b/nvme-print.h @@ -106,6 +106,8 @@ static inline struct print_ops *nvme_get_json_print_ops(enum nvme_print_flags fl #endif /* !CONFIG_JSONC */ +struct print_ops *nvme_get_stdout_print_ops(enum nvme_print_flags flags); + void nvme_show_status(int status); void nvme_show_lba_status_info(__u32 result); void nvme_show_relatives(const char *name); -- 2.49.0