#define WDC_DRIVE_CAP_REASON_ID 0x0000000000010000
#define WDC_DRIVE_CAP_LOG_PAGE_DIR 0x0000000000020000
#define WDC_DRIVE_CAP_NS_RESIZE 0x0000000000040000
+#define WDC_DRIVE_CAP_INFO 0x0000000000080000
#define WDC_DRIVE_CAP_DRIVE_ESSENTIALS 0x0000000100000000
#define WDC_DRIVE_CAP_DUI_DATA 0x0000000200000000
/* Namespace Resize */
#define WDC_NVME_NAMESPACE_RESIZE_OPCODE 0xFB
+/* Drive Info */
+#define WDC_NVME_DRIVE_INFO_OPCODE 0xC6
+#define WDC_NVME_DRIVE_INFO_CMD 0x22
+#define WDC_NVME_DRIVE_INFO_SUBCMD 0x06
+
/* Capture Diagnostics */
#define WDC_NVME_CAP_DIAG_HEADER_TOC_SIZE WDC_NVME_LOG_SIZE_DATA_LEN
#define WDC_NVME_CAP_DIAG_OPCODE 0xE6
static int wdc_dump_telemetry_hdr(int fd, int log_id, struct nvme_telemetry_log_page_hdr *log_hdr);
static int wdc_log_page_directory(int argc, char **argv, struct command *command,
struct plugin *plugin);
+static int wdc_do_drive_info(int fd, __u32 *result);
+static int wdc_vs_drive_info(int argc, char **argv, struct command *command,
+ struct plugin *plugin);
/* Drive log data size */
struct wdc_log_size {
WDC_DRIVE_CAP_RESIZE | WDC_DRIVE_CAP_CLEAR_PCIE |
WDC_DRIVE_CAP_FW_ACTIVATE_HISTORY | WDC_DRIVE_CAP_CLEAR_FW_ACT_HISTORY |
WDC_DRVIE_CAP_DISABLE_CTLR_TELE_LOG | WDC_DRIVE_CAP_REASON_ID |
- WDC_DRIVE_CAP_LOG_PAGE_DIR);
+ WDC_DRIVE_CAP_LOG_PAGE_DIR | WDC_DRIVE_CAP_INFO);
/* verify the 0xCA log page is supported */
if (wdc_nvme_check_supported_log_page(fd, WDC_NVME_GET_DEVICE_INFO_LOG_OPCODE) == true)
return ret;
}
+static int wdc_do_drive_info(int fd, __u32 *result)
+{
+ int ret;
+ struct nvme_admin_cmd admin_cmd;
+
+ memset(&admin_cmd, 0, sizeof (struct nvme_admin_cmd));
+ admin_cmd.opcode = WDC_NVME_DRIVE_INFO_OPCODE;
+ admin_cmd.cdw12 = ((WDC_NVME_DRIVE_INFO_SUBCMD << WDC_NVME_SUBCMD_SHIFT) |
+ WDC_NVME_DRIVE_INFO_CMD);
+
+ ret = nvme_submit_admin_passthru(fd, &admin_cmd);
+
+ if (!ret && result)
+ *result = admin_cmd.result;
+
+ return ret;
+}
+
+
static int wdc_drive_resize(int argc, char **argv,
struct command *command, struct plugin *plugin)
{
return ret;
}
+
+static int wdc_vs_drive_info(int argc, char **argv,
+ struct command *command, struct plugin *plugin)
+{
+ const char *desc = "Send a vs-drive-info command.";
+ uint64_t capabilities = 0;
+ int fd, ret;
+ __le32 result;
+ __u16 size;
+ double rev;
+
+ OPT_ARGS(opts) = {
+ OPT_END()
+ };
+
+ fd = parse_and_open(argc, argv, desc, opts);
+ if (fd < 0)
+ return fd;
+
+ wdc_check_device(fd);
+ capabilities = wdc_get_drive_capabilities(fd);
+ if ((capabilities & WDC_DRIVE_CAP_INFO) == WDC_DRIVE_CAP_INFO) {
+ ret = wdc_do_drive_info(fd, &result);
+ } else {
+ fprintf(stderr, "ERROR : WDC: unsupported device for this command\n");
+ ret = -1;
+ }
+
+ if (!ret) {
+ size = (__u16)((cpu_to_le32(result) & 0xffff0000) >> 16);
+ rev = (double)(cpu_to_le32(result) & 0x0000ffff);
+
+ printf("Drive HW Revison: %4.1f\n", (.1 * rev));
+ printf("FTL Unit Size: 0x%x KB\n", size);
+ }
+
+ fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(ret), ret);
+ return ret;
+}
+
+