Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F162920304
D32700.id97800.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
19 KB
Referenced Files
None
Subscribers
None
D32700.id97800.diff
View Options
Index: sbin/nvmecontrol/Makefile
===================================================================
--- sbin/nvmecontrol/Makefile
+++ sbin/nvmecontrol/Makefile
@@ -10,6 +10,7 @@
SRCS+= passthru.c
SRCS+= identify_ext.c nvme_util.c nc_util.c
SRCS+= selftest.c
+SRCS+= feature.c
MAN= nvmecontrol.8
LDFLAGS+= -rdynamic
LIBADD+= util
Index: sbin/nvmecontrol/feature.c
===================================================================
--- /dev/null
+++ sbin/nvmecontrol/feature.c
@@ -0,0 +1,674 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (C) 2021 Wanpeng Qian <wanpengqian@gmail.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * without modification, immediately at the beginning of the file.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/ioccom.h>
+
+#include <err.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+#include "nvmecontrol.h"
+
+/* Tables for command line parsing */
+
+static cmd_fn_t feat;
+static cmd_fn_t featget;
+static cmd_fn_t featset;
+static cmd_fn_t featsummary;
+
+#define NONE8 0xffu
+#define NONE32 0xffffffffu
+#define NONE64 0xffffffffffffffffull
+#define OPT(l, s, t, opt, addr, desc) { l, s, t, &opt.addr, desc }
+#define OPT_END { NULL, 0, arg_none, NULL, NULL }
+
+/* Convert a zero-based value into a one-based value */
+#define ONE_BASED(zero) ((zero) + 1)
+/* Convert a one-based value into a zero-based value */
+#define ZERO_BASED(one) ((one) - 1)
+
+#define NVME_FEAT_GET_SEL_SHIFT (8)
+#define NVME_FEAT_GET_SEL_MASK (0x7)
+#define NVME_FEAT_GET_FID_SHIFT (0)
+#define NVME_FEAT_GET_FID_MASK (0xFF)
+
+#define NVME_FEAT_SET_SV_SHIFT (31)
+#define NVME_FEAT_SET_SV_MASK (0x1)
+#define NVME_FEAT_SET_FID_SHIFT (0)
+#define NVME_FEAT_SET_FID_MASK (0xFF)
+
+#define NVME_FEAT_ARBITRATION_HPW_SHIFT (24)
+#define NVME_FEAT_ARBITRATION_HPW_MASK (0xFF)
+#define NVME_FEAT_ARBITRATION_MPW_SHIFT (16)
+#define NVME_FEAT_ARBITRATION_MPW_MASK (0xFF)
+#define NVME_FEAT_ARBITRATION_LPW_SHIFT (8)
+#define NVME_FEAT_ARBITRATION_LPW_MASK (0xFF)
+#define NVME_FEAT_ARBITRATION_AB_SHIFT (0)
+#define NVME_FEAT_ARBITRATION_AB_MASK (0x7)
+
+#define NVME_FEAT_POWER_MANAGEMENT_WH_SHIFT (5)
+#define NVME_FEAT_POWER_MANAGEMENT_WH_MASK (0x7)
+#define NVME_FEAT_POWER_MANAGEMENT_PS_SHIFT (0)
+#define NVME_FEAT_POWER_MANAGEMENT_PS_MASK (0x1F)
+
+#define NVME_FEAT_TEMPERATURE_THRESHOLD_THSEL_SHIFT (20)
+#define NVME_FEAT_TEMPERATURE_THRESHOLD_THSEL_MASK (0x3)
+#define NVME_FEAT_TEMPERATURE_THRESHOLD_TMPSEL_SHIFT (16)
+#define NVME_FEAT_TEMPERATURE_THRESHOLD_TMPSEL_MASK (0xFF)
+#define NVME_FEAT_TEMPERATURE_THRESHOLD_TMPTH_SHIFT (0)
+#define NVME_FEAT_TEMPERATURE_THRESHOLD_TMPTH_MASK (0xFFFF)
+
+#define NVME_FEAT_ERROR_RECOVERY_DULBE_SHIFT (16)
+#define NVME_FEAT_ERROR_RECOVERY_DULBE_MASK (0x1)
+#define NVME_FEAT_ERROR_RECOVERY_TLER_SHIFT (0)
+#define NVME_FEAT_ERROR_RECOVERY_TLER_MASK (0xFF)
+
+#define NVME_FEAT_NUMBER_OF_QUEUES_NCQA_SHIFT (16)
+#define NVME_FEAT_NUMBER_OF_QUEUES_NCQA_MASK (0xFFFF)
+#define NVME_FEAT_NUMBER_OF_QUEUES_NSQA_SHIFT (0)
+#define NVME_FEAT_NUMBER_OF_QUEUES_NSQA_MASK (0xFFFF)
+
+#define NVME_FEAT_INTERRUPT_COALESCING_TIME_SHIFT (8)
+#define NVME_FEAT_INTERRUPT_COALESCING_TIME_MASK (0xFF)
+#define NVME_FEAT_INTERRUPT_COALESCING_THR_SHIFT (0)
+#define NVME_FEAT_INTERRUPT_COALESCING_THR_MASK (0xFF)
+
+#define NVME_FEAT_INTERRUPT_VECTOR_CONFIGURATION_CD_SHIFT (16)
+#define NVME_FEAT_INTERRUPT_VECTOR_CONFIGURATION_CD_MASK (0x1)
+#define NVME_FEAT_INTERRUPT_VECTOR_CONFIGURATION_IV_SHIFT (0)
+#define NVME_FEAT_INTERRUPT_VECTOR_CONFIGURATION_IV_MASK (0xFF)
+
+#define NVME_FEAT_WRITE_ATOMICITY_DN_SHIFT (0)
+#define NVME_FEAT_WRITE_ATOMICITY_DN_MASK (0x1)
+
+#define NVME_FEAT_ASYNC_EVENT_CONFIGURATION_TLN_SHIFT (10)
+#define NVME_FEAT_ASYNC_EVENT_CONFIGURATION_TLN_MASK (0x1)
+#define NVME_FEAT_ASYNC_EVENT_CONFIGURATION_FAN_SHIFT (9)
+#define NVME_FEAT_ASYNC_EVENT_CONFIGURATION_FAN_MASK (0x1)
+#define NVME_FEAT_ASYNC_EVENT_CONFIGURATION_NAN_SHIFT (8)
+#define NVME_FEAT_ASYNC_EVENT_CONFIGURATION_NAN_MASK (0x1)
+#define NVME_FEAT_ASYNC_EVENT_CONFIGURATION_HCW_SHIFT (0)
+#define NVME_FEAT_ASYNC_EVENT_CONFIGURATION_HCW_MASK (0xFF)
+
+static
+const char *bits[16] = {
+ [ 0] = "0000", [ 1] = "0001", [ 2] = "0010", [ 3] = "0011",
+ [ 4] = "0100", [ 5] = "0101", [ 6] = "0110", [ 7] = "0111",
+ [ 8] = "1000", [ 9] = "1001", [10] = "1010", [11] = "1011",
+ [12] = "1100", [13] = "1101", [14] = "1110", [15] = "1111",
+};
+
+typedef void (*output_fn_t)(const uint8_t fid, uint32_t cdw0);
+
+static const char *
+feat_name_res[] = {
+ [0] = "Reserved",
+ [1] = "Command Arbitration",
+ [2] = "Power Management",
+ [3] = "LBA Range Type",
+ [4] = "Temperature Threshold",
+ [5] = "Error Recovery",
+ [6] = "Volatile Write Cache",
+ [7] = "Number of Queues",
+ [8] = "Interrupt Coalescing",
+ [9] = "Interrupt Vector Configuration",
+ [10] = "Write Atomicity Normal",
+ [11] = "Asynchronous Event Configuration",
+ [12] = "Autonomous Power State Transition",
+ [13] = "Host Memory Buffer",
+ [14] = "Timestamp",
+ [15] = "Keep Alive Timer",
+ [16] = "Host Controlled Thermal Management",
+ [17] = "Non-Operational Power State Config",
+};
+static uint32_t feat_name_res_max = nitems(feat_name_res);
+
+struct summary_data {
+ uint8_t fid;
+ uint8_t sel;
+ uint32_t cdw11;
+};
+
+static const struct summary_data feat_summary_list[] = {
+ { 0x1, 0x0, 0x0 },
+ { 0x2, 0x0, 0x0 },
+ { 0x4, 0x0, 0x0 },
+ { 0x5, 0x0, 0x0 },
+ { 0x7, 0x0, 0x0 },
+ { 0x8, 0x0, 0x0 },
+ { 0x9, 0x0, 0x0 },
+ { 0xa, 0x0, 0x0 },
+ { 0xb, 0x0, 0x0 },
+};
+static uint32_t feat_summary_list_max = nitems(feat_summary_list);
+
+static struct cmd feat_cmd = {
+ .name = "feature",
+ .fn = feat,
+ .descr = "Get Feature & Set Feature for specified device",
+ .ctx_size = 0,
+ .opts = NULL,
+ .args = NULL,
+};
+
+CMD_COMMAND(feat_cmd);
+
+static struct get_options {
+ uint8_t fid;
+ uint8_t sel;
+ uint32_t cdw11;
+ bool binary;
+ const char *dev;
+} get_opt = {
+ .fid = NONE8,
+ .sel = 0,
+ .cdw11 = 0,
+ .binary = false,
+ .dev = NULL,
+};
+
+static const struct opts get_opts[] = {
+ OPT("fid", 'f', arg_uint8, get_opt, fid,
+ "feature id (required)"),
+ OPT("sel", 's', arg_uint8, get_opt, sel,
+ "[0-3]current/default/saved/supported"),
+ OPT("binary", 'b', arg_none, get_opt, binary,
+ "print result binary"),
+ OPT("cdw11", '1', arg_uint32, get_opt, cdw11,
+ "dword 11 value"),
+ OPT_END
+};
+
+static const struct args get_args[] = {
+ { arg_string, &get_opt.dev, "controller-id" },
+ { arg_none, NULL, NULL },
+};
+
+static struct cmd get_cmd = {
+ .name = "get",
+ .fn = featget,
+ .descr = "Get Feature for specified device",
+ .ctx_size = sizeof(get_opt),
+ .opts = get_opts,
+ .args = get_args,
+};
+
+CMD_SUBCOMMAND(feat_cmd, get_cmd);
+
+static struct set_options {
+ uint8_t fid;
+ bool save;
+ uint32_t cdw11;
+ uint32_t cdw12;
+ uint32_t cdw13;
+ uint32_t cdw14;
+ uint32_t cdw15;
+ const char *dev;
+} set_opt = {
+ .fid = NONE8,
+ .save = false,
+ .cdw11 = 0,
+ .cdw12 = 0,
+ .cdw13 = 0,
+ .cdw14 = 0,
+ .cdw15 = 0,
+ .dev = NULL,
+};
+
+static const struct opts set_opts[] = {
+ OPT("fid", 'f', arg_uint8, set_opt, fid,
+ "feature id (required)"),
+ OPT("save", 's', arg_none, set_opt, save,
+ "the controller shall save the attribute"),
+ OPT("cdw11", '1', arg_uint32, set_opt, cdw11,
+ "dword 11 value"),
+ OPT("cdw12", '2', arg_uint32, set_opt, cdw12,
+ "dword 12 value"),
+ OPT("cdw13", '3', arg_uint32, set_opt, cdw13,
+ "dword 13 value"),
+ OPT("cdw14", '4', arg_uint32, set_opt, cdw14,
+ "dword 14 value"),
+ OPT("cdw15", '5', arg_uint32, set_opt, cdw15,
+ "dword 15 value"),
+ OPT_END
+};
+
+static const struct args set_args[] = {
+ { arg_string, &set_opt.dev, "controller-id" },
+ { arg_none, NULL, NULL },
+};
+
+static struct cmd set_cmd = {
+ .name = "set",
+ .fn = featset,
+ .descr = "Set Feature for specified device",
+ .ctx_size = sizeof(set_opt),
+ .opts = set_opts,
+ .args = set_args,
+};
+
+CMD_SUBCOMMAND(feat_cmd, set_cmd);
+
+static struct summary_options {
+ const char *dev;
+} summary_opt = {
+ .dev = NULL,
+};
+
+static const struct args summary_args[] = {
+ { arg_string, &summary_opt.dev, "controller-id" },
+ { arg_none, NULL, NULL },
+};
+
+static struct cmd summary_cmd = {
+ .name = "summary",
+ .fn = featsummary,
+ .descr = "Show Feature summary for specified device",
+ .ctx_size = sizeof(summary_opt),
+ .opts = NULL,
+ .args = summary_args,
+};
+
+CMD_SUBCOMMAND(feat_cmd, summary_cmd);
+
+static void
+print_feat_arbitration(uint32_t cdw0)
+{
+
+ printf(" Arbitration Burst (AB): ");
+ if ((cdw0 & NVME_FEAT_ARBITRATION_AB_MASK) == NVME_FEAT_ARBITRATION_AB_MASK)
+ printf("no limit\n");
+ else
+ printf("%d\n", 1 << (cdw0 & NVME_FEAT_ARBITRATION_AB_MASK));
+ printf(" Low Priority Weight (LPW): %d\n",
+ ONE_BASED((cdw0 >> NVME_FEAT_ARBITRATION_LPW_SHIFT) &
+ NVME_FEAT_ARBITRATION_LPW_MASK));
+ printf(" Medium Priority Weight (MPW): %d\n",
+ ONE_BASED((cdw0 >> NVME_FEAT_ARBITRATION_MPW_SHIFT) &
+ NVME_FEAT_ARBITRATION_MPW_MASK));
+ printf(" High Priority Weight (HPW): %d\n",
+ ONE_BASED((cdw0 >> NVME_FEAT_ARBITRATION_HPW_SHIFT) &
+ NVME_FEAT_ARBITRATION_HPW_MASK));
+}
+
+static void
+print_feat_power_management(uint32_t cdw0)
+{
+
+ printf(" Workload Hint (WH): %#x\n",
+ (cdw0 >> NVME_FEAT_POWER_MANAGEMENT_WH_SHIFT) &
+ NVME_FEAT_POWER_MANAGEMENT_WH_MASK);
+ printf(" Power State (PS): %#x\n",
+ (cdw0 >> NVME_FEAT_POWER_MANAGEMENT_PS_SHIFT) &
+ NVME_FEAT_POWER_MANAGEMENT_PS_MASK);
+}
+
+static void
+print_feat_temperature_threshold(uint32_t cdw0)
+{
+
+ printf(" Threshold Type Select (THSEL): %#x\n",
+ (cdw0 >> NVME_FEAT_TEMPERATURE_THRESHOLD_THSEL_SHIFT) &
+ NVME_FEAT_TEMPERATURE_THRESHOLD_THSEL_MASK);
+ printf(" Threshold Temperature Select (TMPSEL): %#x\n",
+ (cdw0 >> NVME_FEAT_TEMPERATURE_THRESHOLD_TMPSEL_SHIFT) &
+ NVME_FEAT_TEMPERATURE_THRESHOLD_TMPSEL_MASK);
+ printf(" Temperature Threshold (TMPTH): ");
+ print_temp((cdw0 >> NVME_FEAT_TEMPERATURE_THRESHOLD_TMPTH_SHIFT) &
+ NVME_FEAT_TEMPERATURE_THRESHOLD_TMPTH_MASK);
+}
+
+static void
+print_feat_error_recovery(uint32_t cdw0)
+{
+
+ printf(" Deallocated or Unwritten Logical Block Error Enable (DULBE): %d\n",
+ (cdw0 >> NVME_FEAT_ERROR_RECOVERY_DULBE_SHIFT) &
+ NVME_FEAT_ERROR_RECOVERY_DULBE_MASK);
+ printf(" Time Limited Error Recovery (TLER): %d of 100ms\n",
+ (cdw0 >> NVME_FEAT_ERROR_RECOVERY_TLER_SHIFT) &
+ NVME_FEAT_ERROR_RECOVERY_TLER_MASK);
+}
+
+static void
+print_feat_number_of_queues(uint32_t cdw0)
+{
+
+ printf(" Number of I/O Completion Queues Allocated (NCQA): %d\n",
+ ONE_BASED((cdw0 >> NVME_FEAT_NUMBER_OF_QUEUES_NCQA_SHIFT) &
+ NVME_FEAT_NUMBER_OF_QUEUES_NCQA_MASK));
+ printf(" Number of I/O Submission Queues Allocated (NSQA): %d\n",
+ ONE_BASED((cdw0 >> NVME_FEAT_NUMBER_OF_QUEUES_NSQA_SHIFT) &
+ NVME_FEAT_NUMBER_OF_QUEUES_NSQA_MASK));
+}
+
+static void
+print_feat_interrupt_coalescing(uint32_t cdw0)
+{
+
+ printf(" Aggregation Time (TIME): %d\n",
+ (cdw0 >> NVME_FEAT_INTERRUPT_COALESCING_TIME_SHIFT) &
+ NVME_FEAT_INTERRUPT_COALESCING_TIME_MASK);
+ printf(" Aggregation Threshold (THR): %d\n",
+ (cdw0 >> NVME_FEAT_INTERRUPT_COALESCING_THR_SHIFT) &
+ NVME_FEAT_INTERRUPT_COALESCING_THR_MASK);
+}
+
+static void
+print_feat_interrupt_vector_configuration(uint32_t cdw0)
+{
+
+ printf(" Coalescing Disable (CD): %d\n",
+ (cdw0 >> NVME_FEAT_INTERRUPT_VECTOR_CONFIGURATION_CD_SHIFT) &
+ NVME_FEAT_INTERRUPT_VECTOR_CONFIGURATION_CD_MASK);
+ printf(" Interrupt Vector (IV): %d\n",
+ (cdw0 >> NVME_FEAT_INTERRUPT_VECTOR_CONFIGURATION_IV_SHIFT) &
+ NVME_FEAT_INTERRUPT_VECTOR_CONFIGURATION_IV_MASK);
+}
+
+static void
+print_feat_write_atomicity(uint32_t cdw0)
+{
+
+ printf(" Disable Normal (DN): %d\n",
+ (cdw0 >> NVME_FEAT_WRITE_ATOMICITY_DN_SHIFT) &
+ NVME_FEAT_WRITE_ATOMICITY_DN_MASK);
+}
+
+static void
+print_feat_async_event_configuration(uint32_t cdw0)
+{
+
+ printf(" Telemetry Log Notices (TLN): %d\n",
+ (cdw0 >> NVME_FEAT_ASYNC_EVENT_CONFIGURATION_TLN_SHIFT) &
+ NVME_FEAT_ASYNC_EVENT_CONFIGURATION_TLN_MASK);
+ printf(" Firmware Activation Notices (FAN): %d\n",
+ (cdw0 >> NVME_FEAT_ASYNC_EVENT_CONFIGURATION_FAN_SHIFT) &
+ NVME_FEAT_ASYNC_EVENT_CONFIGURATION_FAN_MASK);
+ printf(" Namespace Attribute Notices (NAN): %d\n",
+ (cdw0 >> NVME_FEAT_ASYNC_EVENT_CONFIGURATION_NAN_SHIFT) &
+ NVME_FEAT_ASYNC_EVENT_CONFIGURATION_NAN_MASK);
+ printf(" SMART / Health Critical Warnings (HCW): 0x%x\n",
+ (cdw0 >> NVME_FEAT_ASYNC_EVENT_CONFIGURATION_HCW_SHIFT) &
+ NVME_FEAT_ASYNC_EVENT_CONFIGURATION_HCW_MASK);
+}
+
+static void
+output_human(const uint8_t fid, uint32_t cdw0)
+{
+
+ switch (fid) {
+ case NVME_FEAT_ARBITRATION:
+ print_feat_arbitration(cdw0);
+ break;
+ case NVME_FEAT_POWER_MANAGEMENT:
+ print_feat_power_management(cdw0);
+ break;
+ case NVME_FEAT_LBA_RANGE_TYPE:
+ printf(" cdw0 = 0x%#08x\n", cdw0);
+ break;
+ case NVME_FEAT_TEMPERATURE_THRESHOLD:
+ print_feat_temperature_threshold(cdw0);
+ break;
+ case NVME_FEAT_ERROR_RECOVERY:
+ print_feat_error_recovery(cdw0);
+ break;
+ case NVME_FEAT_VOLATILE_WRITE_CACHE:
+ printf(" cdw0 = 0x%#08x\n", cdw0);
+ break;
+ case NVME_FEAT_NUMBER_OF_QUEUES:
+ print_feat_number_of_queues(cdw0);
+ break;
+ case NVME_FEAT_INTERRUPT_COALESCING:
+ print_feat_interrupt_coalescing(cdw0);
+ break;
+ case NVME_FEAT_INTERRUPT_VECTOR_CONFIGURATION:
+ print_feat_interrupt_vector_configuration(cdw0);
+ break;
+ case NVME_FEAT_WRITE_ATOMICITY:
+ print_feat_write_atomicity(cdw0);
+ break;
+ case NVME_FEAT_ASYNC_EVENT_CONFIGURATION:
+ print_feat_async_event_configuration(cdw0);
+ break;
+ case NVME_FEAT_AUTONOMOUS_POWER_STATE_TRANSITION:
+ case NVME_FEAT_HOST_MEMORY_BUFFER:
+ case NVME_FEAT_TIMESTAMP:
+ case NVME_FEAT_KEEP_ALIVE_TIMER:
+ case NVME_FEAT_HOST_CONTROLLED_THERMAL_MGMT:
+ case NVME_FEAT_NON_OP_POWER_STATE_CONFIG:
+ case NVME_FEAT_READ_RECOVERY_LEVEL_CONFIG:
+ case NVME_FEAT_PREDICTABLE_LATENCY_MODE_WINDOW:
+ case NVME_FEAT_LBA_STATUS_INFORMATION_ATTRIBUTES:
+ case NVME_FEAT_HOST_BEHAVIOR_SUPPORT:
+ case NVME_FEAT_SANITIZE_CONFIG:
+ case NVME_FEAT_ENDURANCE_GROUP_EVENT_CONFIGURATION:
+ case NVME_FEAT_SOFTWARE_PROGRESS_MARKER:
+ case NVME_FEAT_HOST_IDENTIFIER:
+ case NVME_FEAT_RESERVATION_NOTIFICATION_MASK:
+ case NVME_FEAT_RESERVATION_PERSISTENCE:
+ case NVME_FEAT_NAMESPACE_WRITE_PROTECTION_CONFIG:
+ default:
+ printf(" cdw0 = 0x%#08x\n", cdw0);
+ break;
+ }
+}
+
+static void
+output_binary_uint4(uint8_t v){
+ printf("%s", bits[v & 0x0F]);
+}
+
+static void
+output_binary(const uint8_t fid __unused, uint32_t cdw0)
+{
+ uint32_t i;
+
+ printf("cdw0 = ");
+ for(i = 0; i < sizeof(cdw0) * 2; i++) {
+ output_binary_uint4(cdw0 >> i*4);
+ printf(" ");
+ }
+ printf("\n");
+}
+
+static void
+featget(const struct cmd *f, int argc, char *argv[])
+{
+ struct nvme_pt_command pt;
+ uint8_t fid, sel;
+ uint32_t cdw0, cdw11;
+ int fd;
+ output_fn_t output_fn;
+
+ if (arg_parse(argc, argv, f))
+ return;
+
+ if (get_opt.fid == NONE8) {
+ fprintf(stderr,
+ "feature id not specified\n");
+ arg_help(argc, argv, f);
+ }
+ if (get_opt.sel > 0x3) {
+ fprintf(stderr,
+ "select value over range\n");
+ arg_help(argc, argv, f);
+ }
+
+ open_dev(get_opt.dev, &fd, 1, 1);
+
+ fid = get_opt.fid;
+ sel = get_opt.sel;
+ cdw11 = get_opt.cdw11;
+
+ memset(&pt, 0, sizeof(pt));
+ pt.cmd.opc = NVME_OPC_GET_FEATURES;
+ pt.cmd.cdw10 = htole32((sel << NVME_FEAT_GET_SEL_SHIFT) |
+ (fid << NVME_FEAT_GET_FID_SHIFT));
+ pt.cmd.cdw11 = htole32(cdw11);
+ pt.buf = NULL;
+ pt.len = 0;
+ pt.is_read = 1;
+
+ if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0)
+ err(EX_IOERR, "passthrough request failed");
+
+ printf("Get Feature: %s(0x%x)\n",
+ (fid < feat_name_res_max ? feat_name_res[fid] : "\0"), fid);
+
+ if (nvme_completion_is_error(&pt.cpl))
+ errx(EX_IOERR, "get feature returned error");
+
+ cdw0 = pt.cpl.cdw0;
+
+ output_fn = output_human;
+ if ( get_opt.binary )
+ output_fn = output_binary;
+
+ output_fn(fid, cdw0);
+
+ close(fd);
+ exit(0);
+}
+
+static void
+featset(const struct cmd *f, int argc, char *argv[])
+{
+ struct nvme_pt_command pt;
+ uint8_t fid;
+ bool save;
+ uint32_t cdw11, cdw12, cdw13, cdw14, cdw15;
+ int fd;
+
+ if (arg_parse(argc, argv, f))
+ return;
+
+ if (set_opt.fid == NONE8) {
+ fprintf(stderr,
+ "feature id not specified\n");
+ arg_help(argc, argv, f);
+ }
+
+ fid = set_opt.fid;
+ save = set_opt.save;
+ cdw11 = set_opt.cdw11;
+ cdw12 = set_opt.cdw12;
+ cdw13 = set_opt.cdw13;
+ cdw14 = set_opt.cdw14;
+ cdw15 = set_opt.cdw15;
+
+ open_dev(set_opt.dev, &fd, 1, 1);
+
+ memset(&pt, 0, sizeof(pt));
+ pt.cmd.opc = NVME_OPC_SET_FEATURES;
+ pt.cmd.cdw10 = htole32((save << NVME_FEAT_SET_SV_SHIFT) |
+ (fid << NVME_FEAT_SET_FID_SHIFT));
+ pt.cmd.cdw11 = htole32(cdw11);
+ pt.cmd.cdw12 = htole32(cdw12);
+ pt.cmd.cdw13 = htole32(cdw13);
+ pt.cmd.cdw14 = htole32(cdw14);
+ pt.cmd.cdw15 = htole32(cdw15);
+ pt.buf = NULL;
+ pt.len = 0;
+ pt.is_read = 0;
+
+ if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0)
+ err(EX_IOERR, "passthrough request failed");
+
+ printf("Set Feature: %s(0x%x)\n",
+ (fid < feat_name_res_max ? feat_name_res[fid] : "\0"), fid);
+
+ if (nvme_completion_is_error(&pt.cpl))
+ errx(EX_IOERR, "set feature returned error");
+ else
+ printf("set feature success\n");
+
+ close(fd);
+ exit(0);
+}
+
+static void
+featsummary(const struct cmd *f, int argc, char *argv[])
+{
+ struct nvme_pt_command pt;
+ uint8_t fid, sel;
+ uint32_t cdw0, cdw11;
+ int fd;
+ uint32_t i;
+
+ if (arg_parse(argc, argv, f))
+ return;
+
+ open_dev(summary_opt.dev, &fd, 1, 1);
+
+ for(i = 0; i < feat_summary_list_max; i++) {
+ fid = feat_summary_list[i].fid;
+ sel = feat_summary_list[i].sel;
+ cdw11 = feat_summary_list[i].cdw11;
+
+ memset(&pt, 0, sizeof(pt));
+ pt.cmd.opc = NVME_OPC_GET_FEATURES;
+ pt.cmd.cdw10 = htole32((sel << NVME_FEAT_GET_SEL_SHIFT) |
+ (fid << NVME_FEAT_GET_FID_SHIFT));
+ pt.cmd.cdw11 = htole32(cdw11);
+ pt.buf = NULL;
+ pt.len = 0;
+ pt.is_read = 1;
+
+ if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0)
+ continue;
+
+ printf("%s(0x%x)\n",
+ (fid < feat_name_res_max ? feat_name_res[fid] : "\0"), fid);
+
+ if (nvme_completion_is_error(&pt.cpl))
+ continue;
+
+ cdw0 = pt.cpl.cdw0;
+ output_human(fid, cdw0);
+ }
+
+ close(fd);
+ exit(0);
+}
+
+static void
+feat(const struct cmd *nf __unused, int argc, char *argv[])
+{
+
+ cmd_dispatch(argc, argv, &feat_cmd);
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Jul 19, 7:44 AM (3 h, 57 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35226573
Default Alt Text
D32700.id97800.diff (19 KB)
Attached To
Mode
D32700: nvmecontrol: Implement Get/Set Feature for nvmecontrol
Attached
Detach File
Event Timeline
Log In to Comment