summaryrefslogtreecommitdiffstats
path: root/plugins/seagate
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-29 04:41:05 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-29 04:41:05 +0000
commit1cc8413aaf5f8fa6595aece1933462c096e88639 (patch)
treee97b4f25c511372d73bdd96c389c5f468d99138a /plugins/seagate
parentInitial commit. (diff)
downloadnvme-cli-5cfa46883ee24249a66010b27ade5caf2917916a.tar.xz
nvme-cli-5cfa46883ee24249a66010b27ade5caf2917916a.zip
Adding upstream version 2.4+really2.3.upstream/2.4+really2.3upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'plugins/seagate')
-rw-r--r--plugins/seagate/seagate-diag.h388
-rw-r--r--plugins/seagate/seagate-nvme.c2042
-rw-r--r--plugins/seagate/seagate-nvme.h51
3 files changed, 2481 insertions, 0 deletions
diff --git a/plugins/seagate/seagate-diag.h b/plugins/seagate/seagate-diag.h
new file mode 100644
index 0000000..39f0d39
--- /dev/null
+++ b/plugins/seagate/seagate-diag.h
@@ -0,0 +1,388 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Do NOT modify or remove this copyright and license
+ *
+ * Copyright (c) 2017-2018 Seagate Technology LLC and/or its Affiliates, All Rights Reserved
+ *
+ * ******************************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * \file seagate-diag.h
+ * \brief This file defines the functions and macros to make building a nvme-cli seagate plug-in.
+ *
+ * Author: Debabrata Bardhan <debabrata.bardhan@seagate.com>
+ */
+
+
+#ifndef SEAGATE_NVME_H
+#define SEAGATE_NVME_H
+
+#define SEAGATE_PLUGIN_VERSION_MAJOR 1
+#define SEAGATE_PLUGIN_VERSION_MINOR 2
+
+#define SEAGATE_OCP_PLUGIN_VERSION_MAJOR 1
+#define SEAGATE_OCP_PLUGIN_VERSION_MINOR 0
+
+#define PERSIST_FILE_SIZE (2764800)
+#define ONE_MB (1048576) /* (1024 * 1024) */
+#define PERSIST_CHUNK (65536) /* (1024 * 64) */
+#define FOUR_KB (4096)
+#define STX_NUM_LEGACY_DRV (123)
+
+
+const char* stx_jag_pan_mn[STX_NUM_LEGACY_DRV] = {"ST1000KN0002", "ST1000KN0012", "ST2000KN0002",
+ "ST2000KN0012", "ST4000KN0002", "XP1600HE10002",
+ "XP1600HE10012", "XP1600HE30002", "XP1600HE30012",
+ "XP1920LE10002", "XP1920LE10012", "XP1920LE30002",
+ "XP1920LE30012", "XP3200HE10002", "XP3200HE10012",
+ "XP3840LE10002", "XP3840LE10012", "XP400HE30002",
+ "XP400HE30012", "XP400HE30022", "XP400HE30032",
+ "XP480LE30002", "XP480LE30012", "XP480LE30022",
+ "XP480LE30032", "XP800HE10002", "XP800HE10012",
+ "XP800HE30002", "XP800HE30012", "XP800HE30022",
+ "XP800HE30032", "XP960LE10002", "XP960LE10012",
+ "XP960LE30002", "XP960LE30012", "XP960LE30022",
+ "XP960LE30032", "XP256LE30011", "XP256LE30021",
+ "XP7680LE80002", "XP7680LE80003", "XP15360LE80003",
+ "XP30720LE80003", "XP7200-1A2048", "XP7200-1A4096",
+ "XP7201-2A2048", "XP7201-2A4096", "XP7200-1A8192",
+ "ST1000HM0021", "ST1000HM0031", "ST1000HM0061",
+ "ST1000HM0071", "ST1000HM0081", "ST1200HM0001",
+ "ST1600HM0031", "ST1800HM0001", "ST1800HM0011",
+ "ST2000HM0011", "ST2000HM0031", "ST400HM0061",
+ "ST400HM0071", "ST500HM0021", "ST500HM0031",
+ "ST500HM0061", "ST500HM0071", "ST500HM0081",
+ "ST800HM0061", "ST800HM0071", "ST1600HM0011",
+ "ST1600KN0001", "ST1600KN0011", "ST1920HM0001",
+ "ST1920KN0001", "ST1920KN0011", "ST400HM0021",
+ "ST400KN0001", "ST400KN0011", "ST480HM0001",
+ "ST480KN0001", "ST480KN0011", "ST800HM0021",
+ "ST800KN0001", "ST800KN0011", "ST960HM0001",
+ "ST960KN0001", "ST960KN0011", "XF1441-1AA251024",
+ "XF1441-1AA252048", "XF1441-1AA25512", "XF1441-1AB251024",
+ "XF1441-1AB252048", "XF1441-1AB25512", "XF1441-1BA251024",
+ "XF1441-1BA252048", "XF1441-1BA25512", "XF1441-1BB251024",
+ "XF1441-1BB252048", "XF1441-1BB25512", "ST400HM0031",
+ "ST400KN0021", "ST400KN0031", "ST480HM0011",
+ "ST480KN0021", "ST480KN0031", "ST800HM0031",
+ "ST800KN0021", "ST800KN0031", "ST960HM0011",
+ "ST960KN0021", "ST960KN0031", "XM1441-1AA111024",
+ "XM1441-1AA112048", "XM1441-1AA11512", "XM1441-1AA801024",
+ "XM1441-1AA80512", "XM1441-1AB111024", "XM1441-1AB112048",
+ "XM1441-1BA111024", "XM1441-1BA112048", "XM1441-1BA11512",
+ "XM1441-1BA801024", "XM1441-1BA80512", "XM1441-1BB112048"};
+
+
+/***************************
+*Supported Log-Pages from FW
+***************************/
+
+typedef struct __attribute__((__packed__)) log_page_map_entry {
+ __u32 LogPageID;
+ __u32 LogPageSignature;
+ __u32 LogPageVersion;
+} log_page_map_entry;
+
+#define MAX_SUPPORTED_LOG_PAGE_ENTRIES ((4096 - sizeof(__u32)) / sizeof(log_page_map_entry))
+
+typedef struct __attribute__((__packed__)) log_page_map {
+ __u32 NumLogPages;
+ log_page_map_entry LogPageEntry[ MAX_SUPPORTED_LOG_PAGE_ENTRIES ];
+} log_page_map;
+/* EOF Supported Log-Pages from FW */
+
+
+/***************************
+* Extended-SMART Information
+***************************/
+#define NUMBER_EXTENDED_SMART_ATTRIBUTES 42
+
+typedef enum _EXTENDED_SMART_VERSION_
+{
+ EXTENDED_SMART_VERSION_NONE,
+ EXTENDED_SMART_VERSION_GEN,
+ EXTENDED_SMART_VERSION_VENDOR1,
+} EXTENDED_SMART_VERSION;
+
+typedef struct __attribute__((__packed__)) _SmartVendorSpecific
+{
+ __u8 AttributeNumber;
+ __u16 SmartStatus;
+ __u8 NominalValue;
+ __u8 LifetimeWorstValue;
+ __u32 Raw0_3;
+ __u8 RawHigh[3];
+} SmartVendorSpecific;
+
+typedef struct __attribute__((__packed__)) _EXTENDED_SMART_INFO_T
+{
+ __u16 Version;
+ SmartVendorSpecific vendorData[NUMBER_EXTENDED_SMART_ATTRIBUTES];
+ __u8 vendor_specific_reserved[6];
+} EXTENDED_SMART_INFO_T;
+
+typedef struct __attribute__((__packed__)) vendor_smart_attribute_data
+{
+ __u8 AttributeNumber;
+ __u8 Rsvd[3];
+ __u32 LSDword;
+ __u32 MSDword;
+} vendor_smart_attribute_data;
+
+struct __attribute__((__packed__)) nvme_temetry_log_hdr
+{
+ __u8 log_id;
+ __u8 rsvd1[4];
+ __u8 ieee_id[3];
+ __le16 tele_data_area1;
+ __le16 tele_data_area2;
+ __le16 tele_data_area3;
+ __u8 rsvd14[368];
+ __u8 tele_data_aval;
+ __u8 tele_data_gen_num;
+ __u8 reason_identifier[128];
+};
+
+typedef struct __attribute__((__packed__)) _U128
+{
+ __u64 LS__u64;
+ __u64 MS__u64;
+} U128;
+
+typedef struct __attribute__((__packed__)) _vendor_log_page_CF_Attr
+{
+ __u16 SuperCapCurrentTemperature;
+ __u16 SuperCapMaximumTemperature;
+ __u8 SuperCapStatus;
+ __u8 Reserved5to7[3];
+ U128 DataUnitsReadToDramNamespace;
+ U128 DataUnitsWrittenToDramNamespace;
+ __u64 DramCorrectableErrorCount;
+ __u64 DramUncorrectableErrorCount;
+} vendor_log_page_CF_Attr;
+
+typedef struct __attribute__((__packed__)) _vendor_log_page_CF
+{
+ vendor_log_page_CF_Attr AttrCF;
+ __u8 Vendor_Specific_Reserved[ 456 ]; /* 56-511 */
+} vendor_log_page_CF;
+
+typedef struct __attribute__((__packed__)) _STX_EXT_SMART_LOG_PAGE_C0
+{
+ U128 phyMediaUnitsWrt;
+ U128 phyMediaUnitsRd;
+ __u64 badUsrNandBlocks;
+ __u64 badSysNandBlocks;
+ __u64 xorRecoveryCnt;
+ __u64 ucRdEc;
+ __u64 softEccEc;
+ __u64 etoeCrrCnt;
+ __u64 sysDataUsed : 8;
+ __u64 refreshCount : 56;
+ __u64 usrDataEraseCnt;
+ __u16 thermalThrottling;
+ __u8 dssdSpecVerErrata;
+ __u16 dssdSpecVerPoint;
+ __u16 dssdSpecVerMinor;
+ __u8 dssdSpecVerMajor;
+ __u64 pcieCorrEc;
+ __u32 incompleteShutdowns;
+ __u32 rsvd_116_119;
+ __u8 freeBlocks;
+ __u8 rsvd_121_127[7];
+ __u16 capHealth;
+ __u8 nvmeErrataVer;
+ __u8 rsvd_131_135[5];
+ __u64 unalignedIO;
+ __u64 secVerNum;
+ __u64 totalNUSE;
+ U128 plpStartCnt;
+ U128 enduranceEstimate;
+ __u64 pcieLinkRetCnt;
+ __u64 powStateChangeCnt;
+ __u8 rsvd_208_493[286];
+ __u16 logPageVer;
+ U128 logPageGUID;
+} STX_EXT_SMART_LOG_PAGE_C0;
+
+/* EOF Extended-SMART Information*/
+
+
+/**************************
+* PCIE ERROR INFORMATION
+**************************/
+typedef struct __attribute__((__packed__)) pcie_error_log_page
+{
+ __u32 Version;
+ __u32 BadDllpErrCnt;
+ __u32 BadTlpErrCnt;
+ __u32 RcvrErrCnt;
+ __u32 ReplayTOErrCnt;
+ __u32 ReplayNumRolloverErrCnt;
+ __u32 FCProtocolErrCnt;
+ __u32 DllpProtocolErrCnt;
+ __u32 CmpltnTOErrCnt;
+ __u32 RcvrQOverflowErrCnt;
+ __u32 UnexpectedCplTlpErrCnt;
+ __u32 CplTlpURErrCnt;
+ __u32 CplTlpCAErrCnt;
+ __u32 ReqCAErrCnt;
+ __u32 ReqURErrCnt;
+ __u32 EcrcErrCnt;
+ __u32 MalformedTlpErrCnt;
+ __u32 CplTlpPoisonedErrCnt;
+ __u32 MemRdTlpPoisonedErrCnt;
+} pcie_error_log_page;
+/*EOF PCIE ERROR INFORMATION */
+
+/**************************************
+* FW Activation History Log INFORMATION
+***************************************/
+
+typedef struct __attribute__((__packed__)) _stx_fw_activ_his_ele
+{
+ __u8 entryVerNum;
+ __u8 entryLen;
+ __u16 rev02_03;
+ __u16 fwActivCnt;
+ __u64 timeStamp;
+ __u64 rev14_21;
+ __u64 powCycleCnt;
+ __u8 previousFW[8];
+ __u8 newFW[8];
+ __u8 slotNum;
+ __u8 commitActionType;
+ __u16 result;
+ __u8 rev50_63[14];
+} stx_fw_activ_his_ele;
+
+typedef struct __attribute__((__packed__)) _stx_fw_activ_history_log_page
+{
+ __u8 logID;
+ __u8 rev01_03[3];
+ __u32 numValidFwActHisEnt;
+ stx_fw_activ_his_ele fwActHisEnt[20];
+ __u8 rev1288_4077[2790];
+ __u16 logPageVer;
+ __u8 logPageGUID[16];
+} stx_fw_activ_history_log_page;
+
+/* FW Activation History Log INFORMATION */
+
+
+typedef enum
+{
+ VS_ATTR_SOFT_READ_ERROR_RATE, /* 0 OFFSET : 02 -13 bytes */
+ VS_ATTR_REALLOCATED_SECTOR_COUNT, /* 1 OFFSET : 14 -25 bytes */
+ VS_ATTR_POWER_ON_HOURS, /* 2 OFFSET : 26 -37 bytes */
+ VS_ATTR_POWER_FAIL_EVENT_COUNT, /* 3 OFFSET : 38 -49 bytes */
+ VS_ATTR_DEVICE_POWER_CYCLE_COUNT, /* 4 OFFSET : 50 -61 bytes */
+ VS_ATTR_GB_ERASED, /* 5 OFFSET : 62 -73 bytes */
+ VS_ATTR_LIFETIME_DEVSLEEP_EXIT_COUNT, /* 6 OFFSET : 74 -85 bytes */
+ VS_ATTR_LIFETIME_ENTERING_PS4_COUNT, /* 7 OFFSET : 86 -97 bytes */
+ VS_ATTR_LIFETIME_ENTERING_PS3_COUNT, /* 8 OFFSET : 98 -109 bytes */
+ VS_ATTR_RETIRED_BLOCK_COUNT, /* 9 OFFSET : 110 -121 bytes */
+ VS_ATTR_PROGRAM_FAILURE_COUNT, /* 10 OFFSET : 122 -133 bytes */
+ VS_ATTR_ERASE_FAIL_COUNT, /* 11 OFFSET : 134 -145 bytes */
+ VS_ATTR_AVG_ERASE_COUNT, /* 12 OFFSET : 146 -157 bytes */
+ VS_ATTR_UNEXPECTED_POWER_LOSS_COUNT, /* 13 OFFSET : 158 -169 bytes */
+ VS_ATTR_WEAR_RANGE_DELTA, /* 14 OFFSET : 170 -181 bytes */
+ VS_ATTR_SATA_INTERFACE_DOWNSHIFT_COUNT, /* 15 OFFSET : 182 -193 bytes */
+ VS_ATTR_END_TO_END_CRC_ERROR_COUNT, /* 16 OFFSET : 194 -205 bytes */
+ VS_ATTR_MAX_LIFE_TEMPERATURE, /* 17 OFFSET : 206 -217 bytes */
+ VS_ATTR_UNCORRECTABLE_RAISE_ERRORS, /* 18 OFFSET : 218 -229 bytes */
+ VS_ATTR_DRIVE_LIFE_PROTECTION_STATUS, /* 19 OFFSET : 230 -241 bytes */
+ VS_ATTR_REMAINING_SSD_LIFE, /* 20 OFFSET : 242 -253 bytes */
+ VS_ATTR_LIFETIME_WRITES_TO_FLASH, /* 21 OFFSET : 254 -265 bytes */
+ VS_ATTR_LIFETIME_WRITES_FROM_HOST, /* 22 OFFSET : 266 -277 bytes */
+ VS_ATTR_LIFETIME_READS_TO_HOST, /* 23 OFFSET : 278 -289 bytes */
+ VS_ATTR_FREE_SPACE, /* 24 OFFSET : 290 -301 bytes */
+ VS_ATTR_TRIM_COUNT_LSB, /* 25 OFFSET : 302 -313 bytes */
+ VS_ATTR_TRIM_COUNT_MSB, /* 26 OFFSET : 314 -325 bytes */
+ VS_ATTR_OP_PERCENTAGE, /* 27 OFFSET : 326 -337 bytes */
+ VS_ATTR_RAISE_ECC_CORRECTABLE_ERROR_COUNT, /* 28 OFFSET : 338 -349 bytes */
+ VS_ATTR_UNCORRECTABLE_ECC_ERRORS , /* 29 OFFSET : 350 -361 bytes */
+ VS_ATTR_LIFETIME_WRITES0_TO_FLASH, /* 30 OFFSET : 362-372 bytes */
+ VS_ATTR_LIFETIME_WRITES1_TO_FLASH, /* 31 OFFSET : 374-385 bytes */
+ VS_ATTR_LIFETIME_WRITES0_FROM_HOST, /* 32 OFFSET : 386-397 bytes */
+ VS_ATTR_LIFETIME_WRITES1_FROM_HOST, /* 33 OFFSET : 398-409 bytes */
+ VS_ATTR_LIFETIME_READ0_FROM_HOST, /* 34 OFFSET : 410-421 bytes */
+ VS_ATTR_LIFETIME_READ1_FROM_HOST, /* 35 OFFSET : 422-433 bytes */
+ VS_ATTR_PCIE_PHY_CRC_ERROR, /* 36 OFFSET : 434-445 bytes */
+ VS_ATTR_BAD_BLOCK_COUNT_SYSTEM, /* 37 OFFSET : 446-457 bytes */
+ VS_ATTR_BAD_BLOCK_COUNT_USER, /* 38 OFFSET : 458-469 bytes */
+ VS_ATTR_THERMAL_THROTTLING_STATUS, /* 39 OFFSET : 470-481 bytes */
+ VS_ATTR_POWER_CONSUMPTION, /* 40 OFFSET : 482-493 bytes */
+ VS_ATTR_MAX_SOC_LIFE_TEMPERATURE, /* 41 OFFSET : 494-505 bytes */
+ VS_MAX_ATTR_NUMBER
+} extended_smart_attributes;
+
+/*Smart attribute IDs */
+
+typedef enum
+{
+ VS_ATTR_ID_SOFT_READ_ERROR_RATE = 1,
+ VS_ATTR_ID_REALLOCATED_SECTOR_COUNT = 5,
+ VS_ATTR_ID_POWER_ON_HOURS = 9,
+ VS_ATTR_ID_POWER_FAIL_EVENT_COUNT = 11,
+ VS_ATTR_ID_DEVICE_POWER_CYCLE_COUNT = 12,
+ VS_ATTR_ID_RAW_READ_ERROR_RATE = 13,
+ VS_ATTR_ID_GROWN_BAD_BLOCK_COUNT = 40,
+ VS_ATTR_ID_END_2_END_CORRECTION_COUNT = 41,
+ VS_ATTR_ID_MIN_MAX_WEAR_RANGE_COUNT = 42,
+ VS_ATTR_ID_REFRESH_COUNT = 43,
+ VS_ATTR_ID_BAD_BLOCK_COUNT_USER = 44,
+ VS_ATTR_ID_BAD_BLOCK_COUNT_SYSTEM = 45,
+ VS_ATTR_ID_THERMAL_THROTTLING_STATUS = 46,
+ VS_ATTR_ID_ALL_PCIE_CORRECTABLE_ERROR_COUNT = 47,
+ VS_ATTR_ID_ALL_PCIE_UNCORRECTABLE_ERROR_COUNT = 48,
+ VS_ATTR_ID_INCOMPLETE_SHUTDOWN_COUNT = 49,
+ VS_ATTR_ID_GB_ERASED_LSB = 100,
+ VS_ATTR_ID_GB_ERASED_MSB = 101,
+ VS_ATTR_ID_LIFETIME_ENTERING_PS4_COUNT = 102,
+ VS_ATTR_ID_LIFETIME_ENTERING_PS3_COUNT = 103,
+ VS_ATTR_ID_LIFETIME_DEVSLEEP_EXIT_COUNT = 104,
+ VS_ATTR_ID_RETIRED_BLOCK_COUNT = 170,
+ VS_ATTR_ID_PROGRAM_FAILURE_COUNT = 171,
+ VS_ATTR_ID_ERASE_FAIL_COUNT = 172,
+ VS_ATTR_ID_AVG_ERASE_COUNT = 173,
+ VS_ATTR_ID_UNEXPECTED_POWER_LOSS_COUNT = 174,
+ VS_ATTR_ID_WEAR_RANGE_DELTA = 177,
+ VS_ATTR_ID_SATA_INTERFACE_DOWNSHIFT_COUNT = 183,
+ VS_ATTR_ID_END_TO_END_CRC_ERROR_COUNT = 184,
+ VS_ATTR_ID_UNCORRECTABLE_READ_ERRORS = 188,
+ VS_ATTR_ID_MAX_LIFE_TEMPERATURE = 194,
+ VS_ATTR_ID_RAISE_ECC_CORRECTABLE_ERROR_COUNT = 195,
+ VS_ATTR_ID_UNCORRECTABLE_RAISE_ERRORS = 198,
+ VS_ATTR_ID_DRIVE_LIFE_PROTECTION_STATUS = 230,
+ VS_ATTR_ID_REMAINING_SSD_LIFE = 231,
+ VS_ATTR_ID_LIFETIME_WRITES_TO_FLASH_LSB = 233,
+ VS_ATTR_ID_LIFETIME_WRITES_TO_FLASH_MSB = 234,
+ VS_ATTR_ID_LIFETIME_WRITES_FROM_HOST_LSB = 241,
+ VS_ATTR_ID_LIFETIME_WRITES_FROM_HOST_MSB = 242,
+ VS_ATTR_ID_LIFETIME_READS_TO_HOST_LSB = 243,
+ VS_ATTR_ID_LIFETIME_READS_TO_HOST_MSB = 244,
+ VS_ATTR_ID_FREE_SPACE = 245,
+ VS_ATTR_ID_TRIM_COUNT_LSB = 250,
+ VS_ATTR_ID_TRIM_COUNT_MSB = 251,
+ VS_ATTR_ID_OP_PERCENTAGE = 252,
+ VS_ATTR_ID_MAX_SOC_LIFE_TEMPERATURE = 253,
+} smart_attributes_ids;
+
+#define TELEMETRY_BLOCKS_TO_READ 8
+
+void seaget_d_raw(unsigned char *buf, int len, int fd);
+
+
+#define DP_CLASS_ID_FULL 0
+
+#endif
diff --git a/plugins/seagate/seagate-nvme.c b/plugins/seagate/seagate-nvme.c
new file mode 100644
index 0000000..1bd30a5
--- /dev/null
+++ b/plugins/seagate/seagate-nvme.c
@@ -0,0 +1,2042 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Do NOT modify or remove this copyright and license
+ *
+ * Copyright (c) 2017-2018 Seagate Technology LLC and/or its Affiliates, All Rights Reserved
+ *
+ * ******************************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * \file seagate-nvme.c
+ * \brief This file defines the functions and macros to make building a nvme-cli seagate plug-in.
+ *
+ * Author: Debabrata Bardhan <debabrata.bardhan@seagate.com>
+ */
+
+
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include "common.h"
+#include "nvme.h"
+#include "libnvme.h"
+#include "plugin.h"
+#include "linux/types.h"
+#include "nvme-print.h"
+#include <time.h>
+
+#define CREATE_CMD
+
+#include "seagate-nvme.h"
+#include "seagate-diag.h"
+
+
+/***************************************
+ * Command for "log-pages-supp"
+ ***************************************/
+static char *log_pages_supp_print(__u32 pageID)
+{
+ switch (pageID) {
+ case 0x01:
+ return "ERROR_INFORMATION";
+ break;
+ case 0x02:
+ return "SMART_INFORMATION";
+ break;
+ case 0x03:
+ return "FW_SLOT_INFORMATION";
+ break;
+ case 0x04:
+ return "CHANGED_NAMESPACE_LIST";
+ break;
+ case 0x05:
+ return "COMMANDS_SUPPORTED_AND_EFFECTS";
+ break;
+ case 0x06:
+ return "DEVICE_SELF_TEST";
+ break;
+ case 0x07:
+ return "TELEMETRY_HOST_INITIATED";
+ break;
+ case 0x08:
+ return "TELEMETRY_CONTROLLER_INITIATED";
+ break;
+ case 0xC0:
+ return "VS_MEDIA_SMART_LOG";
+ break;
+ case 0xC1:
+ return "VS_DEBUG_LOG1";
+ break;
+ case 0xC2:
+ return "VS_SEC_ERROR_LOG_PAGE";
+ break;
+ case 0xC3:
+ return "VS_LIFE_TIME_DRIVE_HISTORY";
+ break;
+ case 0xC4:
+ return "VS_EXTENDED_SMART_INFO";
+ break;
+ case 0xC5:
+ return "VS_LIST_SUPPORTED_LOG_PAGE";
+ break;
+ case 0xC6:
+ return "VS_POWER_MONITOR_LOG_PAGE";
+ break;
+ case 0xC7:
+ return "VS_CRITICAL_EVENT_LOG_PAGE";
+ break;
+ case 0xC8:
+ return "VS_RECENT_DRIVE_HISTORY";
+ break;
+ case 0xC9:
+ return "VS_SEC_ERROR_LOG_PAGE";
+ break;
+ case 0xCA:
+ return "VS_LIFE_TIME_DRIVE_HISTORY";
+ break;
+ case 0xCB:
+ return "VS_PCIE_ERROR_LOG_PAGE";
+ break;
+ case 0xCF:
+ return "DRAM Supercap SMART Attributes";
+ break;
+ case 0xD6:
+ return "VS_OEM2_WORK_LOAD";
+ break;
+ case 0xD7:
+ return "VS_OEM2_FW_SECURITY";
+ break;
+ case 0xD8:
+ return "VS_OEM2_REVISION";
+ break;
+ default:
+ return "UNKNOWN";
+ break;
+ }
+}
+
+static int stx_is_jag_pan(char *devMN)
+{
+ int match_found = 1; /* found = 0, not_found = 1 */
+
+ for (int i = 0; i < STX_NUM_LEGACY_DRV; i++) {
+ match_found = strncmp(devMN, stx_jag_pan_mn[i], strlen(stx_jag_pan_mn[i]));
+ if (match_found == 0) {
+ break;
+ }
+ }
+
+ return match_found;
+}
+
+
+static void json_log_pages_supp(log_page_map *logPageMap)
+{
+ struct json_object *root;
+ struct json_object *logPages;
+ __u32 i = 0;
+
+ root = json_create_object();
+ logPages = json_create_array();
+ json_object_add_value_array(root, "supported_log_pages", logPages);
+
+ for (i = 0; i < le32_to_cpu(logPageMap->NumLogPages); i++) {
+ struct json_object *lbaf = json_create_object();
+ json_object_add_value_int(lbaf, "logpage_id",
+ le32_to_cpu(logPageMap->LogPageEntry[i].LogPageID));
+ json_object_add_value_string(lbaf, "logpage_name",
+ log_pages_supp_print(le32_to_cpu(logPageMap->LogPageEntry[i].LogPageID)));
+
+ json_array_add_value_object(logPages, lbaf);
+ }
+ json_print_object(root, NULL);
+ json_free_object(root);
+}
+
+static int log_pages_supp(int argc, char **argv, struct command *cmd,
+ struct plugin *plugin)
+{
+ int err = 0;
+ __u32 i = 0;
+ log_page_map logPageMap;
+ const char *desc = "Retrieve Seagate Supported Log-Page information for the given device ";
+ const char *output_format = "output in binary format";
+ struct nvme_dev *dev;
+ int fmt;
+
+ struct config {
+ char *output_format;
+ };
+
+ struct config cfg = {
+ .output_format = "normal",
+ };
+
+ OPT_ARGS(opts) = {
+ OPT_FMT("output-format", 'o', &cfg.output_format, output_format),
+ OPT_END()
+ };
+
+ err = parse_and_open(&dev, argc, argv, desc, opts);
+ if (err)
+ return err;
+ err = nvme_get_log_simple(dev_fd(dev), 0xc5,
+ sizeof(logPageMap), &logPageMap);
+ if (!err) {
+ if (strcmp(cfg.output_format, "json")) {
+ printf ("Seagate Supported Log-pages count :%d\n",
+ le32_to_cpu(logPageMap.NumLogPages));
+ printf ("%-15s %-30s\n", "LogPage-Id", "LogPage-Name");
+
+ for (fmt = 0; fmt < 45; fmt++)
+ printf("-");
+ printf("\n");
+ } else
+ json_log_pages_supp(&logPageMap);
+
+ for (i = 0; i < le32_to_cpu(logPageMap.NumLogPages); i++) {
+ if (strcmp(cfg.output_format, "json")) {
+ printf("0x%-15X",
+ le32_to_cpu(logPageMap.LogPageEntry[i].LogPageID));
+ printf("%-30s\n",
+ log_pages_supp_print(le32_to_cpu(logPageMap.LogPageEntry[i].LogPageID)));
+ }
+ }
+ }
+
+ if (err > 0)
+ nvme_show_status(err);
+ dev_close(dev);
+ return err;
+}
+
+/* EOF Command for "log-pages-supp" */
+
+
+/***************************************
+* Extended-SMART Information
+***************************************/
+static char *print_ext_smart_id(__u8 attrId)
+{
+ switch (attrId) {
+ case VS_ATTR_ID_SOFT_READ_ERROR_RATE:
+ return "Soft ECC error count";
+ break;
+ case VS_ATTR_ID_REALLOCATED_SECTOR_COUNT:
+ return "Bad NAND block count";
+ break;
+ case VS_ATTR_ID_POWER_ON_HOURS:
+ return "Power On Hours";
+ break;
+ case VS_ATTR_ID_POWER_FAIL_EVENT_COUNT:
+ return "Power Fail Event Count";
+ break;
+ case VS_ATTR_ID_DEVICE_POWER_CYCLE_COUNT:
+ return "Device Power Cycle Count";
+ break;
+ case VS_ATTR_ID_RAW_READ_ERROR_RATE:
+ return "Raw Read Error Count";
+ break;
+ case VS_ATTR_ID_GROWN_BAD_BLOCK_COUNT:
+ return "Bad NAND block count";
+ break;
+ case VS_ATTR_ID_END_2_END_CORRECTION_COUNT:
+ return "SSD End to end correction counts";
+ break;
+ case VS_ATTR_ID_MIN_MAX_WEAR_RANGE_COUNT:
+ return "User data erase counts";
+ break;
+ case VS_ATTR_ID_REFRESH_COUNT:
+ return "Refresh count";
+ break;
+ case VS_ATTR_ID_BAD_BLOCK_COUNT_USER:
+ return "User data erase fail count";
+ break;
+ case VS_ATTR_ID_BAD_BLOCK_COUNT_SYSTEM:
+ return "System area erase fail count";
+ break;
+ case VS_ATTR_ID_THERMAL_THROTTLING_STATUS:
+ return "Thermal throttling status and count";
+ break;
+ case VS_ATTR_ID_ALL_PCIE_CORRECTABLE_ERROR_COUNT:
+ return "PCIe Correctable Error count";
+ break;
+ case VS_ATTR_ID_ALL_PCIE_UNCORRECTABLE_ERROR_COUNT:
+ return "PCIe Uncorrectable Error count";
+ break;
+ case VS_ATTR_ID_INCOMPLETE_SHUTDOWN_COUNT:
+ return "Incomplete shutdowns";
+ break;
+ case VS_ATTR_ID_GB_ERASED_LSB:
+ return "LSB of Flash GB erased";
+ break;
+ case VS_ATTR_ID_GB_ERASED_MSB:
+ return "MSB of Flash GB erased";
+ break;
+ case VS_ATTR_ID_LIFETIME_DEVSLEEP_EXIT_COUNT:
+ return "LIFETIME_DEV_SLEEP_EXIT_COUNT";
+ break;
+ case VS_ATTR_ID_LIFETIME_ENTERING_PS4_COUNT:
+ return "LIFETIME_ENTERING_PS4_COUNT";
+ break;
+ case VS_ATTR_ID_LIFETIME_ENTERING_PS3_COUNT:
+ return "LIFETIME_ENTERING_PS3_COUNT";
+ break;
+ case VS_ATTR_ID_RETIRED_BLOCK_COUNT:
+ return "Retired block count";
+ break;
+ case VS_ATTR_ID_PROGRAM_FAILURE_COUNT:
+ return "Program fail count";
+ break;
+ case VS_ATTR_ID_ERASE_FAIL_COUNT:
+ return "Erase Fail Count";
+ break;
+ case VS_ATTR_ID_AVG_ERASE_COUNT:
+ return "System data % used";
+ break;
+ case VS_ATTR_ID_UNEXPECTED_POWER_LOSS_COUNT:
+ return "Unexpected power loss count";
+ break;
+ case VS_ATTR_ID_WEAR_RANGE_DELTA:
+ return "Wear range delta";
+ break;
+ case VS_ATTR_ID_SATA_INTERFACE_DOWNSHIFT_COUNT:
+ return "PCIE_INTF_DOWNSHIFT_COUNT";
+ break;
+ case VS_ATTR_ID_END_TO_END_CRC_ERROR_COUNT:
+ return "E2E_CRC_ERROR_COUNT";
+ break;
+ case VS_ATTR_ID_UNCORRECTABLE_READ_ERRORS:
+ return "Uncorrectable Read Error Count";
+ break;
+ case VS_ATTR_ID_MAX_LIFE_TEMPERATURE:
+ return "Max lifetime temperature";
+ break;
+ case VS_ATTR_ID_RAISE_ECC_CORRECTABLE_ERROR_COUNT:
+ return "RAIS_ECC_CORRECT_ERR_COUNT";
+ break;
+ case VS_ATTR_ID_UNCORRECTABLE_RAISE_ERRORS:
+ return "Uncorrectable RAISE error count";
+ break;
+ case VS_ATTR_ID_DRIVE_LIFE_PROTECTION_STATUS:
+ return "DRIVE_LIFE_PROTECTION_STATUS";
+ break;
+ case VS_ATTR_ID_REMAINING_SSD_LIFE:
+ return "Remaining SSD life";
+ break;
+ case VS_ATTR_ID_LIFETIME_WRITES_TO_FLASH_LSB:
+ return "LSB of Physical (NAND) bytes written";
+ break;
+ case VS_ATTR_ID_LIFETIME_WRITES_TO_FLASH_MSB:
+ return "MSB of Physical (NAND) bytes written";
+ break;
+ case VS_ATTR_ID_LIFETIME_WRITES_FROM_HOST_LSB:
+ return "LSB of Physical (HOST) bytes written";
+ break;
+ case VS_ATTR_ID_LIFETIME_WRITES_FROM_HOST_MSB:
+ return "MSB of Physical (HOST) bytes written";
+ break;
+ case VS_ATTR_ID_LIFETIME_READS_TO_HOST_LSB:
+ return "LSB of Physical (NAND) bytes read";
+ break;
+ case VS_ATTR_ID_LIFETIME_READS_TO_HOST_MSB:
+ return "MSB of Physical (NAND) bytes read";
+ break;
+ case VS_ATTR_ID_FREE_SPACE:
+ return "Free Space";
+ break;
+ case VS_ATTR_ID_TRIM_COUNT_LSB:
+ return "LSB of Trim count";
+ break;
+ case VS_ATTR_ID_TRIM_COUNT_MSB:
+ return "MSB of Trim count";
+ break;
+ case VS_ATTR_ID_OP_PERCENTAGE:
+ return "OP percentage";
+ break;
+ case VS_ATTR_ID_MAX_SOC_LIFE_TEMPERATURE:
+ return "Max lifetime SOC temperature";
+ break;
+ default:
+ return "Un-Known";
+ }
+}
+
+static __u64 smart_attribute_vs(__u16 verNo, SmartVendorSpecific attr)
+{
+ __u64 val = 0;
+ vendor_smart_attribute_data *attrVendor;
+
+ /**
+ * These are all Vendor A specific attributes.
+ */
+ if (verNo >= EXTENDED_SMART_VERSION_VENDOR1) {
+ attrVendor = (vendor_smart_attribute_data *)&attr;
+ memcpy(&val, &(attrVendor->LSDword), sizeof(val));
+ return val;
+ } else
+ return le32_to_cpu(attr.Raw0_3);
+}
+
+static void print_smart_log(__u16 verNo, SmartVendorSpecific attr, int lastAttr)
+{
+ static __u64 lsbGbErased = 0, msbGbErased = 0, lsbLifWrtToFlash = 0, msbLifWrtToFlash = 0,
+ lsbLifWrtFrmHost = 0, msbLifWrtFrmHost = 0, lsbLifRdToHost = 0, msbLifRdToHost = 0, lsbTrimCnt = 0, msbTrimCnt = 0;
+ char buf[40] = {0};
+ char strBuf[35] = {0};
+ int hideAttr = 0;
+
+ if (attr.AttributeNumber == VS_ATTR_ID_GB_ERASED_LSB) {
+ lsbGbErased = smart_attribute_vs(verNo, attr);
+ hideAttr = 1;
+ }
+
+ if (attr.AttributeNumber == VS_ATTR_ID_GB_ERASED_MSB) {
+ msbGbErased = smart_attribute_vs(verNo, attr);
+ hideAttr = 1;
+ }
+
+ if (attr.AttributeNumber == VS_ATTR_ID_LIFETIME_WRITES_TO_FLASH_LSB) {
+ lsbLifWrtToFlash = smart_attribute_vs(verNo, attr);
+ hideAttr = 1;
+ }
+
+ if (attr.AttributeNumber == VS_ATTR_ID_LIFETIME_WRITES_TO_FLASH_MSB) {
+ msbLifWrtToFlash = smart_attribute_vs(verNo, attr);
+ hideAttr = 1;
+ }
+
+ if (attr.AttributeNumber == VS_ATTR_ID_LIFETIME_WRITES_FROM_HOST_LSB) {
+ lsbLifWrtFrmHost = smart_attribute_vs(verNo, attr);
+ hideAttr = 1;
+ }
+
+ if (attr.AttributeNumber == VS_ATTR_ID_LIFETIME_WRITES_FROM_HOST_MSB) {
+ msbLifWrtFrmHost = smart_attribute_vs(verNo, attr);
+ hideAttr = 1;
+ }
+
+ if (attr.AttributeNumber == VS_ATTR_ID_LIFETIME_READS_TO_HOST_LSB) {
+ lsbLifRdToHost = smart_attribute_vs(verNo, attr);
+ hideAttr = 1;
+ }
+
+ if (attr.AttributeNumber == VS_ATTR_ID_LIFETIME_READS_TO_HOST_MSB) {
+ msbLifRdToHost = smart_attribute_vs(verNo, attr);
+ hideAttr = 1;
+ }
+
+ if (attr.AttributeNumber == VS_ATTR_ID_TRIM_COUNT_LSB) {
+ lsbTrimCnt = smart_attribute_vs(verNo, attr);
+ hideAttr = 1;
+ }
+
+ if (attr.AttributeNumber == VS_ATTR_ID_TRIM_COUNT_MSB) {
+ msbTrimCnt = smart_attribute_vs(verNo, attr);
+ hideAttr = 1;
+ }
+
+ if ((attr.AttributeNumber != 0) && (hideAttr != 1)) {
+ printf("%-40s", print_ext_smart_id(attr.AttributeNumber));
+ printf("%-15d", attr.AttributeNumber);
+ printf(" 0x%016"PRIx64"\n", (uint64_t)smart_attribute_vs(verNo, attr));
+ }
+
+ if (lastAttr == 1) {
+
+ sprintf(strBuf, "%s", (print_ext_smart_id(VS_ATTR_ID_GB_ERASED_LSB) + 7));
+ printf("%-40s", strBuf);
+
+ printf("%-15d", VS_ATTR_ID_GB_ERASED_MSB << 8 | VS_ATTR_ID_GB_ERASED_LSB);
+
+ sprintf(buf, "0x%016"PRIx64"%016"PRIx64"", (uint64_t)msbGbErased, (uint64_t)lsbGbErased);
+ printf(" %s\n", buf);
+
+ sprintf(strBuf, "%s", (print_ext_smart_id(VS_ATTR_ID_LIFETIME_WRITES_TO_FLASH_LSB) + 7));
+ printf("%-40s", strBuf);
+
+ printf("%-15d", VS_ATTR_ID_LIFETIME_WRITES_TO_FLASH_MSB << 8 | VS_ATTR_ID_LIFETIME_WRITES_TO_FLASH_LSB);
+
+ sprintf(buf, "0x%016"PRIx64"%016"PRIx64"", (uint64_t)msbLifWrtToFlash, (uint64_t)lsbLifWrtToFlash);
+ printf(" %s\n", buf);
+
+ sprintf(strBuf, "%s", (print_ext_smart_id(VS_ATTR_ID_LIFETIME_WRITES_FROM_HOST_LSB) + 7));
+ printf("%-40s", strBuf);
+
+ printf("%-15d", VS_ATTR_ID_LIFETIME_WRITES_FROM_HOST_MSB << 8 | VS_ATTR_ID_LIFETIME_WRITES_FROM_HOST_LSB);
+
+ sprintf(buf, "0x%016"PRIx64"%016"PRIx64"", (uint64_t)msbLifWrtFrmHost, (uint64_t)lsbLifWrtFrmHost);
+ printf(" %s\n", buf);
+
+ sprintf(strBuf, "%s", (print_ext_smart_id(VS_ATTR_ID_LIFETIME_READS_TO_HOST_LSB) + 7));
+ printf("%-40s", strBuf);
+
+ printf("%-15d", VS_ATTR_ID_LIFETIME_READS_TO_HOST_MSB << 8 | VS_ATTR_ID_LIFETIME_READS_TO_HOST_LSB);
+
+ sprintf(buf, "0x%016"PRIx64"%016"PRIx64"", (uint64_t)msbLifRdToHost, (uint64_t)lsbLifRdToHost);
+ printf(" %s\n", buf);
+
+ sprintf(strBuf, "%s", (print_ext_smart_id(VS_ATTR_ID_TRIM_COUNT_LSB) + 7));
+ printf("%-40s", strBuf);
+
+ printf("%-15d", VS_ATTR_ID_TRIM_COUNT_MSB << 8 | VS_ATTR_ID_TRIM_COUNT_LSB);
+
+ sprintf(buf, "0x%016"PRIx64"%016"PRIx64"", (uint64_t)msbTrimCnt, (uint64_t)lsbTrimCnt);
+ printf(" %s\n", buf);
+
+ }
+}
+
+static void json_print_smart_log(struct json_object *root, EXTENDED_SMART_INFO_T *ExtdSMARTInfo)
+{
+ struct json_object *lbafs;
+ int index = 0;
+
+ static __u64 lsbGbErased = 0, msbGbErased = 0, lsbLifWrtToFlash = 0, msbLifWrtToFlash = 0,
+ lsbLifWrtFrmHost = 0, msbLifWrtFrmHost = 0, lsbLifRdToHost = 0, msbLifRdToHost = 0, lsbTrimCnt = 0, msbTrimCnt = 0;
+ char buf[40] = {0};
+
+ lbafs = json_create_array();
+ json_object_add_value_array(root, "Extended-SMART-Attributes", lbafs);
+
+ for (index = 0; index < NUMBER_EXTENDED_SMART_ATTRIBUTES; index++) {
+ struct json_object *lbaf = json_create_object();
+ if (ExtdSMARTInfo->vendorData[index].AttributeNumber != 0) {
+ json_object_add_value_string(lbaf, "attribute_name", print_ext_smart_id(ExtdSMARTInfo->vendorData[index].AttributeNumber));
+ json_object_add_value_int(lbaf, "attribute_id", ExtdSMARTInfo->vendorData[index].AttributeNumber);
+ json_object_add_value_int(lbaf, "attribute_value", smart_attribute_vs(ExtdSMARTInfo->Version, ExtdSMARTInfo->vendorData[index]));
+ json_array_add_value_object(lbafs, lbaf);
+
+ if (ExtdSMARTInfo->vendorData[index].AttributeNumber == VS_ATTR_ID_GB_ERASED_LSB)
+ lsbGbErased = smart_attribute_vs(ExtdSMARTInfo->Version, ExtdSMARTInfo->vendorData[index]);
+
+ if (ExtdSMARTInfo->vendorData[index].AttributeNumber == VS_ATTR_ID_GB_ERASED_MSB)
+ msbGbErased = smart_attribute_vs(ExtdSMARTInfo->Version, ExtdSMARTInfo->vendorData[index]);
+
+ if (ExtdSMARTInfo->vendorData[index].AttributeNumber == VS_ATTR_ID_LIFETIME_WRITES_TO_FLASH_LSB)
+ lsbLifWrtToFlash = smart_attribute_vs(ExtdSMARTInfo->Version, ExtdSMARTInfo->vendorData[index]);
+
+ if (ExtdSMARTInfo->vendorData[index].AttributeNumber == VS_ATTR_ID_LIFETIME_WRITES_TO_FLASH_MSB)
+ msbLifWrtToFlash = smart_attribute_vs(ExtdSMARTInfo->Version, ExtdSMARTInfo->vendorData[index]);
+
+ if (ExtdSMARTInfo->vendorData[index].AttributeNumber == VS_ATTR_ID_LIFETIME_WRITES_FROM_HOST_LSB)
+ lsbLifWrtFrmHost = smart_attribute_vs(ExtdSMARTInfo->Version, ExtdSMARTInfo->vendorData[index]);
+
+ if (ExtdSMARTInfo->vendorData[index].AttributeNumber == VS_ATTR_ID_LIFETIME_WRITES_FROM_HOST_MSB)
+ msbLifWrtFrmHost = smart_attribute_vs(ExtdSMARTInfo->Version, ExtdSMARTInfo->vendorData[index]);
+
+ if (ExtdSMARTInfo->vendorData[index].AttributeNumber == VS_ATTR_ID_LIFETIME_READS_TO_HOST_LSB)
+ lsbLifRdToHost = smart_attribute_vs(ExtdSMARTInfo->Version, ExtdSMARTInfo->vendorData[index]);
+
+ if (ExtdSMARTInfo->vendorData[index].AttributeNumber == VS_ATTR_ID_LIFETIME_READS_TO_HOST_MSB)
+ msbLifRdToHost = smart_attribute_vs(ExtdSMARTInfo->Version, ExtdSMARTInfo->vendorData[index]);
+
+ if (ExtdSMARTInfo->vendorData[index].AttributeNumber == VS_ATTR_ID_TRIM_COUNT_LSB)
+ lsbTrimCnt = smart_attribute_vs(ExtdSMARTInfo->Version, ExtdSMARTInfo->vendorData[index]);
+
+ if (ExtdSMARTInfo->vendorData[index].AttributeNumber == VS_ATTR_ID_TRIM_COUNT_MSB)
+ msbTrimCnt = smart_attribute_vs(ExtdSMARTInfo->Version, ExtdSMARTInfo->vendorData[index]);
+ }
+ }
+
+ struct json_object *lbaf = json_create_object();
+
+ json_object_add_value_string(lbaf, "attribute_name", (print_ext_smart_id(VS_ATTR_ID_GB_ERASED_LSB) + 7));
+
+ json_object_add_value_int(lbaf, "attribute_id", VS_ATTR_ID_GB_ERASED_MSB << 8 | VS_ATTR_ID_GB_ERASED_LSB);
+
+ sprintf(buf, "0x%016"PRIx64"%016"PRIx64"", (uint64_t)msbGbErased, (uint64_t)lsbGbErased);
+ json_object_add_value_string(lbaf, "attribute_value", buf);
+ json_array_add_value_object(lbafs, lbaf);
+
+
+ lbaf = json_create_object();
+
+ json_object_add_value_string(lbaf, "attribute_name", (print_ext_smart_id(VS_ATTR_ID_LIFETIME_WRITES_TO_FLASH_LSB) + 7));
+
+ json_object_add_value_int(lbaf, "attribute_id", VS_ATTR_ID_LIFETIME_WRITES_TO_FLASH_MSB << 8 | VS_ATTR_ID_LIFETIME_WRITES_TO_FLASH_LSB);
+
+ sprintf(buf, "0x%016"PRIx64"%016"PRIx64"", (uint64_t)msbLifWrtToFlash, (uint64_t)lsbLifWrtToFlash);
+ json_object_add_value_string(lbaf, "attribute_value", buf);
+ json_array_add_value_object(lbafs, lbaf);
+
+
+ lbaf = json_create_object();
+
+ json_object_add_value_string(lbaf, "attribute_name", (print_ext_smart_id(VS_ATTR_ID_LIFETIME_WRITES_FROM_HOST_LSB) + 7));
+
+ json_object_add_value_int(lbaf, "attribute_id", VS_ATTR_ID_LIFETIME_WRITES_FROM_HOST_MSB << 8 | VS_ATTR_ID_LIFETIME_WRITES_FROM_HOST_LSB);
+
+ sprintf(buf, "0x%016"PRIx64"%016"PRIx64"", (uint64_t)msbLifWrtFrmHost, (uint64_t)lsbLifWrtFrmHost);
+ json_object_add_value_string(lbaf, "attribute_value", buf);
+ json_array_add_value_object(lbafs, lbaf);
+
+
+ lbaf = json_create_object();
+
+ json_object_add_value_string(lbaf, "attribute_name", (print_ext_smart_id(VS_ATTR_ID_LIFETIME_READS_TO_HOST_LSB) + 7));
+
+ json_object_add_value_int(lbaf, "attribute_id", VS_ATTR_ID_LIFETIME_READS_TO_HOST_MSB << 8 | VS_ATTR_ID_LIFETIME_READS_TO_HOST_LSB);
+
+ sprintf(buf, "0x%016"PRIx64"%016"PRIx64"", (uint64_t)msbLifRdToHost, (uint64_t)lsbLifRdToHost);
+ json_object_add_value_string(lbaf, "attribute_value", buf);
+ json_array_add_value_object(lbafs, lbaf);
+
+
+ lbaf = json_create_object();
+
+ json_object_add_value_string(lbaf, "attribute_name", (print_ext_smart_id(VS_ATTR_ID_TRIM_COUNT_LSB) + 7));
+
+ json_object_add_value_int(lbaf, "attribute_id", VS_ATTR_ID_TRIM_COUNT_MSB << 8 | VS_ATTR_ID_TRIM_COUNT_LSB);
+
+ sprintf(buf, "0x%016"PRIx64"%016"PRIx64"", (uint64_t)msbTrimCnt, (uint64_t)lsbTrimCnt);
+ json_object_add_value_string(lbaf, "attribute_value", buf);
+ json_array_add_value_object(lbafs, lbaf);
+}
+
+static void print_smart_log_CF(vendor_log_page_CF *pLogPageCF)
+{
+ __u64 currentTemp, maxTemp;
+ printf("\n\nSeagate DRAM Supercap SMART Attributes :\n");
+ printf("%-39s %-19s \n", "Description", "Supercap Attributes");
+
+ printf("%-40s", "Super-cap current temperature");
+ currentTemp = pLogPageCF->AttrCF.SuperCapCurrentTemperature;
+ printf(" 0x%016"PRIx64"\n", le64_to_cpu(currentTemp));
+
+ maxTemp = pLogPageCF->AttrCF.SuperCapMaximumTemperature;
+ printf("%-40s", "Super-cap maximum temperature");
+ printf(" 0x%016"PRIx64"\n", le64_to_cpu(maxTemp));
+
+ printf("%-40s", "Super-cap status");
+ printf(" 0x%016"PRIx64"\n", le64_to_cpu(pLogPageCF->AttrCF.SuperCapStatus));
+
+ printf("%-40s", "Data units read to DRAM namespace");
+ printf(" 0x%016"PRIx64"%016"PRIx64"\n", le64_to_cpu(pLogPageCF->AttrCF.DataUnitsReadToDramNamespace.MS__u64),
+ le64_to_cpu(pLogPageCF->AttrCF.DataUnitsReadToDramNamespace.LS__u64));
+
+ printf("%-40s", "Data units written to DRAM namespace");
+ printf(" 0x%016"PRIx64"%016"PRIx64"\n", le64_to_cpu(pLogPageCF->AttrCF.DataUnitsWrittenToDramNamespace.MS__u64),
+ le64_to_cpu(pLogPageCF->AttrCF.DataUnitsWrittenToDramNamespace.LS__u64));
+
+ printf("%-40s", "DRAM correctable error count");
+ printf(" 0x%016"PRIx64"\n", le64_to_cpu(pLogPageCF->AttrCF.DramCorrectableErrorCount));
+
+ printf("%-40s", "DRAM uncorrectable error count");
+ printf(" 0x%016"PRIx64"\n", le64_to_cpu(pLogPageCF->AttrCF.DramUncorrectableErrorCount));
+}
+
+static void json_print_smart_log_CF(struct json_object *root, vendor_log_page_CF *pLogPageCF)
+{
+ struct json_object *logPages;
+ unsigned int currentTemp, maxTemp;
+ char buf[40];
+
+ logPages = json_create_array();
+ json_object_add_value_array(root, "DRAM Supercap SMART Attributes", logPages);
+ struct json_object *lbaf = json_create_object();
+
+ currentTemp = pLogPageCF->AttrCF.SuperCapCurrentTemperature;
+ json_object_add_value_string(lbaf, "attribute_name", "Super-cap current temperature");
+ json_object_add_value_int(lbaf, "attribute_value", currentTemp);
+ json_array_add_value_object(logPages, lbaf);
+
+ lbaf = json_create_object();
+ maxTemp = pLogPageCF->AttrCF.SuperCapMaximumTemperature;
+ json_object_add_value_string(lbaf, "attribute_name", "Super-cap maximum temperature");
+ json_object_add_value_int(lbaf, "attribute_value", maxTemp);
+ json_array_add_value_object(logPages, lbaf);
+
+ lbaf = json_create_object();
+ json_object_add_value_string(lbaf, "attribute_name", "Super-cap status");
+ json_object_add_value_int(lbaf, "attribute_value", pLogPageCF->AttrCF.SuperCapStatus);
+ json_array_add_value_object(logPages, lbaf);
+
+ lbaf = json_create_object();
+ json_object_add_value_string(lbaf, "attribute_name", "Data units read to DRAM namespace");
+ memset(buf, 0, sizeof(buf));
+ sprintf(buf, "0x%016"PRIx64"%016"PRIx64"", le64_to_cpu(pLogPageCF->AttrCF.DataUnitsReadToDramNamespace.MS__u64),
+ le64_to_cpu(pLogPageCF->AttrCF.DataUnitsReadToDramNamespace.LS__u64));
+ json_object_add_value_string(lbaf, "attribute_value", buf);
+ json_array_add_value_object(logPages, lbaf);
+
+ lbaf = json_create_object();
+ json_object_add_value_string(lbaf, "attribute_name", "Data units written to DRAM namespace");
+ memset(buf, 0, sizeof(buf));
+ sprintf(buf, "0x%016"PRIx64"%016"PRIx64"", le64_to_cpu(pLogPageCF->AttrCF.DataUnitsWrittenToDramNamespace.MS__u64),
+ le64_to_cpu(pLogPageCF->AttrCF.DataUnitsWrittenToDramNamespace.LS__u64));
+ json_object_add_value_string(lbaf, "attribute_value", buf);
+ json_array_add_value_object(logPages, lbaf);
+
+ lbaf = json_create_object();
+ json_object_add_value_string(lbaf, "attribute_name", "DRAM correctable error count");
+ json_object_add_value_int(lbaf, "attribute_value", pLogPageCF->AttrCF.DramCorrectableErrorCount);
+ json_array_add_value_object(logPages, lbaf);
+
+ lbaf = json_create_object();
+ json_object_add_value_string(lbaf, "attribute_name", "DRAM uncorrectable error count");
+ json_object_add_value_int(lbaf, "attribute_value", pLogPageCF->AttrCF.DramUncorrectableErrorCount);
+ json_array_add_value_object(logPages, lbaf);
+}
+
+
+static void print_stx_smart_log_C0(STX_EXT_SMART_LOG_PAGE_C0 *pLogPageC0)
+{
+ printf("\n\nSeagate SMART Health Attributes :\n");
+ printf("%-39s %-19s \n", "Description", "Health Attributes");
+
+ printf("%-40s", "Physical Media Units Written");
+ printf(" 0x%016"PRIx64"%016"PRIx64"\n", le64_to_cpu(pLogPageC0->phyMediaUnitsWrt.MS__u64),
+ le64_to_cpu(pLogPageC0->phyMediaUnitsWrt.LS__u64));
+
+ printf("%-40s", "Physical Media Units Read");
+ printf(" 0x%016"PRIx64"%016"PRIx64"\n", le64_to_cpu(pLogPageC0->phyMediaUnitsRd.MS__u64),
+ le64_to_cpu(pLogPageC0->phyMediaUnitsRd.LS__u64));
+
+ printf("%-40s", "Bad User NAND Blocks");
+ printf(" 0x%016"PRIx64"\n", le64_to_cpu(pLogPageC0->badUsrNandBlocks));
+
+ printf("%-40s", "Bad System NAND Blocks");
+ printf(" 0x%016"PRIx64"\n", le64_to_cpu(pLogPageC0->badSysNandBlocks));
+
+ printf("%-40s", "XOR Recovery Count");
+ printf(" 0x%016"PRIx64"\n", le64_to_cpu(pLogPageC0->xorRecoveryCnt));
+
+ printf("%-40s", "Uncorrectable Read Error Count");
+ printf(" 0x%016"PRIx64"\n", le64_to_cpu(pLogPageC0->ucRdEc));
+
+ printf("%-40s", "Soft ECC Error Count");
+ printf(" 0x%016"PRIx64"\n", le64_to_cpu(pLogPageC0->softEccEc));
+
+ printf("%-40s", "End to End Correction Counts");
+ printf(" 0x%016"PRIx64"\n", le64_to_cpu(pLogPageC0->etoeCrrCnt));
+
+ printf("%-40s", "System Data Used in Parcent");
+ printf(" 0x%016"PRIx64"\n", le64_to_cpu(pLogPageC0->sysDataUsed));
+
+ printf("%-40s", "Refresh Counts");
+ printf(" 0x%016"PRIx64"\n", le64_to_cpu(pLogPageC0->refreshCount));
+
+ printf("%-40s", "User Data Erase Counts");
+ printf(" 0x%016"PRIx64"\n", le64_to_cpu(pLogPageC0->usrDataEraseCnt));
+
+ printf("%-40s", "Thermal Throttling Status and Count");
+ printf(" 0x%04x\n", le16_to_cpu(pLogPageC0->thermalThrottling));
+
+ printf("%-40s", "DSSD Specification Version");
+ printf(" %d.%d.%d.%d\n", pLogPageC0->dssdSpecVerMajor,
+ le16_to_cpu(pLogPageC0->dssdSpecVerMinor),
+ le16_to_cpu(pLogPageC0->dssdSpecVerPoint),
+ pLogPageC0->dssdSpecVerErrata);
+
+ printf("%-40s", "PCIe Correctable Error Count");
+ printf(" 0x%016"PRIx64"\n", le64_to_cpu(pLogPageC0->pcieCorrEc));
+
+ printf("%-40s", "Incomplete Shutdowns");
+ printf(" 0x%08x\n", le32_to_cpu(pLogPageC0->incompleteShutdowns));
+
+ printf("%-40s", "Free Blocks in Percent");
+ printf(" %d\n", pLogPageC0->freeBlocks);
+
+ printf("%-40s", "Capacitor Health");
+ printf(" 0x%04x\n", le16_to_cpu(pLogPageC0->capHealth));
+
+ printf("%-40s", "NVMe Errata Version");
+ printf(" %c\n", pLogPageC0->nvmeErrataVer);
+
+ printf("%-40s", "Unaligned IO");
+ printf(" 0x%016"PRIx64"\n", le64_to_cpu(pLogPageC0->unalignedIO));
+
+ printf("%-40s", "Security Version Number");
+ printf(" 0x%016"PRIx64"\n", le64_to_cpu(pLogPageC0->secVerNum));
+
+ printf("%-40s", "Total Namespace Utilization");
+ printf(" 0x%016"PRIx64"\n", le64_to_cpu(pLogPageC0->totalNUSE));
+
+ printf("%-40s", "PLP Start Count");
+ printf(" 0x%016"PRIx64"%016"PRIx64"\n", le64_to_cpu(pLogPageC0->plpStartCnt.MS__u64),
+ le64_to_cpu(pLogPageC0->plpStartCnt.LS__u64));
+
+ printf("%-40s", "Endurance Estimate");
+ printf(" 0x%016"PRIx64"%016"PRIx64"\n", le64_to_cpu(pLogPageC0->enduranceEstimate.MS__u64),
+ le64_to_cpu(pLogPageC0->enduranceEstimate.LS__u64));
+
+ printf("%-40s", "PCIe Link Retraining Count");
+ printf(" 0x%016"PRIx64"\n", le64_to_cpu(pLogPageC0->pcieLinkRetCnt));
+
+ printf("%-40s", "Power State Change Count");
+ printf(" 0x%016"PRIx64"\n", le64_to_cpu(pLogPageC0->powStateChangeCnt));
+
+ printf("%-40s", "Log Page Version");
+ printf(" 0x%04x\n", le16_to_cpu(pLogPageC0->logPageVer));
+
+ printf("%-40s", "Log Page GUID");
+ printf(" 0x%016"PRIx64"%016"PRIx64"\n", le64_to_cpu(pLogPageC0->logPageGUID.MS__u64),
+ le64_to_cpu(pLogPageC0->logPageGUID.LS__u64));
+}
+
+static void json_print_stx_smart_log_C0(struct json_object *root, STX_EXT_SMART_LOG_PAGE_C0 *pLogPageC0)
+{
+ struct json_object *logPages;
+ char buf[40];
+
+ logPages = json_create_array();
+ json_object_add_value_array(root, "Seagate SMART Health Attributes", logPages);
+
+ struct json_object *lbaf = json_create_object();
+
+ json_object_add_value_string(lbaf, "attribute_name", "Physical Media Units Written");
+ memset(buf, 0, sizeof(buf));
+ sprintf(buf, "0x%016"PRIx64"%016"PRIx64"", le64_to_cpu(pLogPageC0->phyMediaUnitsWrt.MS__u64),
+ le64_to_cpu(pLogPageC0->phyMediaUnitsWrt.LS__u64));
+ json_object_add_value_string(lbaf, "attribute_value", buf);
+ json_array_add_value_object(logPages, lbaf);
+
+
+ lbaf = json_create_object();
+ json_object_add_value_string(lbaf, "attribute_name", "Physical Media Units Read");
+ memset(buf, 0, sizeof(buf));
+ sprintf(buf, "0x%016"PRIx64"%016"PRIx64"", le64_to_cpu(pLogPageC0->phyMediaUnitsRd.MS__u64),
+ le64_to_cpu(pLogPageC0->phyMediaUnitsRd.LS__u64));
+ json_object_add_value_string(lbaf, "attribute_value", buf);
+ json_array_add_value_object(logPages, lbaf);
+
+ lbaf = json_create_object();
+ json_object_add_value_string(lbaf, "attribute_name", "Bad User NAND Blocks");
+ json_object_add_value_int(lbaf, "attribute_value", le64_to_cpu(pLogPageC0->badUsrNandBlocks));
+ json_array_add_value_object(logPages, lbaf);
+
+ lbaf = json_create_object();
+ json_object_add_value_string(lbaf, "attribute_name", "Bad System NAND Blocks");
+ json_object_add_value_int(lbaf, "attribute_value", le64_to_cpu(pLogPageC0->badSysNandBlocks));
+ json_array_add_value_object(logPages, lbaf);
+
+ lbaf = json_create_object();
+ json_object_add_value_string(lbaf, "attribute_name", "XOR Recovery Count");
+ json_object_add_value_int(lbaf, "attribute_value", le64_to_cpu(pLogPageC0->xorRecoveryCnt));
+ json_array_add_value_object(logPages, lbaf);
+
+ lbaf = json_create_object();
+ json_object_add_value_string(lbaf, "attribute_name", "Uncorrectable Read Error Count");
+ json_object_add_value_int(lbaf, "attribute_value", le64_to_cpu(pLogPageC0->ucRdEc));
+ json_array_add_value_object(logPages, lbaf);
+
+ lbaf = json_create_object();
+ json_object_add_value_string(lbaf, "attribute_name", "Soft ECC Error Count");
+ json_object_add_value_int(lbaf, "attribute_value", le64_to_cpu(pLogPageC0->softEccEc));
+ json_array_add_value_object(logPages, lbaf);
+
+ lbaf = json_create_object();
+ json_object_add_value_string(lbaf, "attribute_name", "End to End Correction Counts");
+ json_object_add_value_int(lbaf, "attribute_value", le64_to_cpu(pLogPageC0->etoeCrrCnt));
+ json_array_add_value_object(logPages, lbaf);
+
+ lbaf = json_create_object();
+ json_object_add_value_string(lbaf, "attribute_name", "System Data Used in Parcent");
+ json_object_add_value_int(lbaf, "attribute_value", le64_to_cpu(pLogPageC0->sysDataUsed));
+ json_array_add_value_object(logPages, lbaf);
+
+ lbaf = json_create_object();
+ json_object_add_value_string(lbaf, "attribute_name", "Refresh Counts");
+ json_object_add_value_int(lbaf, "attribute_value", le64_to_cpu(pLogPageC0->refreshCount));
+ json_array_add_value_object(logPages, lbaf);
+
+ lbaf = json_create_object();
+ json_object_add_value_string(lbaf, "attribute_name", "User Data Erase Counts");
+ json_object_add_value_int(lbaf, "attribute_value", le64_to_cpu(pLogPageC0->usrDataEraseCnt));
+ json_array_add_value_object(logPages, lbaf);
+
+ lbaf = json_create_object();
+ json_object_add_value_string(lbaf, "attribute_name", "Thermal Throttling Status and Count");
+ json_object_add_value_int(lbaf, "attribute_value", le16_to_cpu(pLogPageC0->thermalThrottling));
+ json_array_add_value_object(logPages, lbaf);
+
+ lbaf = json_create_object();
+ json_object_add_value_string(lbaf, "attribute_name", "DSSD Specification Version");
+ memset(buf, 0, sizeof(buf));
+ sprintf(buf, "%d.%d.%d.%d", pLogPageC0->dssdSpecVerMajor,
+ le16_to_cpu(pLogPageC0->dssdSpecVerMinor),
+ le16_to_cpu(pLogPageC0->dssdSpecVerPoint),
+ pLogPageC0->dssdSpecVerErrata);
+ json_object_add_value_string(lbaf, "attribute_value", buf);
+ json_array_add_value_object(logPages, lbaf);
+
+ lbaf = json_create_object();
+ json_object_add_value_string(lbaf, "attribute_name", "PCIe Correctable Error Count");
+ json_object_add_value_int(lbaf, "attribute_value", le64_to_cpu(pLogPageC0->pcieCorrEc));
+ json_array_add_value_object(logPages, lbaf);
+
+ lbaf = json_create_object();
+ json_object_add_value_string(lbaf, "attribute_name", "Incomplete Shutdowns");
+ json_object_add_value_int(lbaf, "attribute_value", le32_to_cpu(pLogPageC0->incompleteShutdowns));
+ json_array_add_value_object(logPages, lbaf);
+
+ lbaf = json_create_object();
+ json_object_add_value_string(lbaf, "attribute_name", "Free Blocks in Percent");
+ json_object_add_value_int(lbaf, "attribute_value", pLogPageC0->freeBlocks);
+ json_array_add_value_object(logPages, lbaf);
+
+ lbaf = json_create_object();
+ json_object_add_value_string(lbaf, "attribute_name", "Capacitor Health");
+ json_object_add_value_int(lbaf, "attribute_value", le16_to_cpu(pLogPageC0->capHealth));
+ json_array_add_value_object(logPages, lbaf);
+
+ lbaf = json_create_object();
+ json_object_add_value_string(lbaf, "attribute_name", "NVMe Errata Version");
+ json_object_add_value_int(lbaf, "attribute_value", pLogPageC0->nvmeErrataVer);
+ json_array_add_value_object(logPages, lbaf);
+
+ lbaf = json_create_object();
+ json_object_add_value_string(lbaf, "attribute_name", "Unaligned IO");
+ json_object_add_value_int(lbaf, "attribute_value", le64_to_cpu(pLogPageC0->unalignedIO));
+ json_array_add_value_object(logPages, lbaf);
+
+ lbaf = json_create_object();
+ json_object_add_value_string(lbaf, "attribute_name", "Security Version Number");
+ json_object_add_value_int(lbaf, "attribute_value", le64_to_cpu(pLogPageC0->secVerNum));
+ json_array_add_value_object(logPages, lbaf);
+
+ lbaf = json_create_object();
+ json_object_add_value_string(lbaf, "attribute_name", "Total Namespace Utilization");
+ json_object_add_value_int(lbaf, "attribute_value", le64_to_cpu(pLogPageC0->totalNUSE));
+ json_array_add_value_object(logPages, lbaf);
+
+ lbaf = json_create_object();
+ json_object_add_value_string(lbaf, "attribute_name", "PLP Start Count");
+ memset(buf, 0, sizeof(buf));
+ sprintf(buf, "0x%016"PRIx64"%016"PRIx64"", le64_to_cpu(pLogPageC0->plpStartCnt.MS__u64),
+ le64_to_cpu(pLogPageC0->plpStartCnt.LS__u64));
+ json_object_add_value_string(lbaf, "attribute_value", buf);
+ json_array_add_value_object(logPages, lbaf);
+
+ lbaf = json_create_object();
+ json_object_add_value_string(lbaf, "attribute_name", "Endurance Estimate");
+ memset(buf, 0, sizeof(buf));
+ sprintf(buf, "0x%016"PRIx64"%016"PRIx64"", le64_to_cpu(pLogPageC0->enduranceEstimate.MS__u64),
+ le64_to_cpu(pLogPageC0->enduranceEstimate.LS__u64));
+ json_object_add_value_string(lbaf, "attribute_value", buf);
+ json_array_add_value_object(logPages, lbaf);
+
+ lbaf = json_create_object();
+ json_object_add_value_string(lbaf, "attribute_name", "PCIe Link Retraining Count");
+ json_object_add_value_int(lbaf, "attribute_value", le64_to_cpu(pLogPageC0->pcieLinkRetCnt));
+ json_array_add_value_object(logPages, lbaf);
+
+ lbaf = json_create_object();
+ json_object_add_value_string(lbaf, "attribute_name", "Power State Change Count");
+ json_object_add_value_int(lbaf, "attribute_value", le64_to_cpu(pLogPageC0->powStateChangeCnt));
+ json_array_add_value_object(logPages, lbaf);
+
+ lbaf = json_create_object();
+ json_object_add_value_string(lbaf, "attribute_name", "Log Page Version");
+ json_object_add_value_int(lbaf, "attribute_value", le16_to_cpu(pLogPageC0->logPageVer));
+ json_array_add_value_object(logPages, lbaf);
+
+ lbaf = json_create_object();
+ json_object_add_value_string(lbaf, "attribute_name", "Log Page GUID");
+ memset(buf, 0, sizeof(buf));
+ sprintf(buf, "0x%016"PRIx64"%016"PRIx64"", le64_to_cpu(pLogPageC0->logPageGUID.MS__u64),
+ le64_to_cpu(pLogPageC0->logPageGUID.LS__u64));
+ json_object_add_value_string(lbaf, "attribute_value", buf);
+ json_array_add_value_object(logPages, lbaf);
+}
+
+static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
+{
+ struct nvme_id_ctrl ctrl;
+ char modelNo[40];
+ STX_EXT_SMART_LOG_PAGE_C0 ehExtSmart;
+ EXTENDED_SMART_INFO_T ExtdSMARTInfo;
+ vendor_log_page_CF logPageCF;
+ struct json_object *root = json_create_object();
+ struct json_object *lbafs = json_create_array();
+ struct json_object *lbafs_ExtSmart, *lbafs_DramSmart;
+
+ const char *desc = "Retrieve the Firmware Activation History for Seagate NVMe drives";
+ const char *output_format = "output in binary format";
+ struct nvme_dev *dev;
+ int err, index = 0;
+ struct config {
+ char *output_format;
+ };
+
+ struct config cfg = {
+ .output_format = "normal",
+ };
+
+ OPT_ARGS(opts) = {
+ OPT_FMT("output-format", 'o', &cfg.output_format, output_format),
+ OPT_END()
+ };
+
+ err = parse_and_open(&dev, argc, argv, desc, opts);
+ if (err) {
+ printf ("\nDevice not found \n");
+ return -1;
+ }
+
+ if (strcmp(cfg.output_format, "json"))
+ printf("Seagate Extended SMART Information :\n");
+
+
+ /**
+ * Here we should identify if the drive is a Panthor or Jaguar.
+ * Here we need to extract the model no from ctrl-id abd use it
+ * to deternine drive family.
+ */
+
+ err = nvme_identify_ctrl(dev_fd(dev), &ctrl);
+ if (!err) {
+ memcpy(modelNo, ctrl.mn, sizeof(modelNo));
+ } else {
+ nvme_show_status(err);
+ return err;
+ }
+
+ if (stx_is_jag_pan(modelNo) == 0) {
+
+ err = nvme_get_log_simple(dev_fd(dev), 0xC4, sizeof(ExtdSMARTInfo), &ExtdSMARTInfo);
+ if (!err) {
+ if (strcmp(cfg.output_format, "json")) {
+ printf("%-39s %-15s %-19s \n", "Description", "Ext-Smart-Id", "Ext-Smart-Value");
+ for (index = 0; index < 80; index++)
+ printf("-");
+ printf("\n");
+ for (index = 0; index < NUMBER_EXTENDED_SMART_ATTRIBUTES; index++)
+ print_smart_log(ExtdSMARTInfo.Version, ExtdSMARTInfo.vendorData[index], index == (NUMBER_EXTENDED_SMART_ATTRIBUTES - 1));
+
+ } else {
+ lbafs_ExtSmart = json_create_object();
+ json_print_smart_log(lbafs_ExtSmart, &ExtdSMARTInfo);
+
+ json_object_add_value_array(root, "SMART-Attributes", lbafs);
+ json_array_add_value_object(lbafs, lbafs_ExtSmart);
+ }
+
+ /**
+ * Next get Log Page 0xCF
+ */
+
+ err = nvme_get_log_simple(dev_fd(dev), 0xCF, sizeof(logPageCF), &logPageCF);
+ if (!err) {
+ if (strcmp(cfg.output_format, "json")) {
+ print_smart_log_CF(&logPageCF);
+ } else {
+ lbafs_DramSmart = json_create_object();
+ json_print_smart_log_CF(lbafs_DramSmart, &logPageCF);
+ json_array_add_value_object(lbafs, lbafs_DramSmart);
+ json_print_object(root, NULL);
+ }
+ } else if (!strcmp(cfg.output_format, "json")) {
+ json_print_object(root, NULL);
+ json_free_object(root);
+ }
+ } else if (err > 0)
+ nvme_show_status(err);
+ } else {
+ err = nvme_get_log_simple(dev_fd(dev), 0xC0, sizeof(ehExtSmart), &ehExtSmart);
+
+ if (!err) {
+ if (strcmp(cfg.output_format, "json")) {
+ print_stx_smart_log_C0(&ehExtSmart);
+
+ } else {
+ lbafs_ExtSmart = json_create_object();
+ json_print_stx_smart_log_C0(lbafs_ExtSmart, &ehExtSmart);
+
+ json_object_add_value_array(root, "SMART-Attributes", lbafs);
+ json_array_add_value_object(lbafs, lbafs_ExtSmart);
+
+ json_print_object(root, NULL);
+ json_free_object(root);
+ }
+ }
+
+ if (err > 0)
+ nvme_show_status(err);
+ }
+
+ err = nvme_get_log_simple(dev_fd(dev), 0xC4,
+ sizeof(ExtdSMARTInfo), &ExtdSMARTInfo);
+ if (!err) {
+ if (strcmp(cfg.output_format, "json")) {
+ printf("%-39s %-15s %-19s \n", "Description", "Ext-Smart-Id", "Ext-Smart-Value");
+ for (index = 0; index < 80; index++)
+ printf("-");
+ printf("\n");
+ for (index = 0; index < NUMBER_EXTENDED_SMART_ATTRIBUTES; index++)
+ print_smart_log(ExtdSMARTInfo.Version, ExtdSMARTInfo.vendorData[index], index == (NUMBER_EXTENDED_SMART_ATTRIBUTES - 1));
+
+ } else {
+ lbafs_ExtSmart = json_create_object();
+ json_print_smart_log(lbafs_ExtSmart, &ExtdSMARTInfo);
+
+ json_object_add_value_array(root, "SMART-Attributes", lbafs);
+ json_array_add_value_object(lbafs, lbafs_ExtSmart);
+ }
+
+ /**
+ * Next get Log Page 0xCF
+ */
+
+ err = nvme_get_log_simple(dev_fd(dev), 0xCF,
+ sizeof(logPageCF), &logPageCF);
+ if (!err) {
+ if (strcmp(cfg.output_format, "json")) {
+ print_smart_log_CF(&logPageCF);
+ } else {
+ lbafs_DramSmart = json_create_object();
+ json_print_smart_log_CF(lbafs_DramSmart, &logPageCF);
+ json_array_add_value_object(lbafs, lbafs_DramSmart);
+ json_print_object(root, NULL);
+ }
+ } else if (!strcmp(cfg.output_format, "json"))
+ json_print_object(root, NULL);
+ } else if (err > 0)
+ nvme_show_status(err);
+
+ dev_close(dev);
+
+ return err;
+}
+
+/*EOF Extended-SMART Information */
+
+/***************************************
+ * Temperature-Stats information
+ ***************************************/
+static void json_temp_stats(__u32 temperature, __u32 PcbTemp, __u32 SocTemp, __u32 maxTemperature,
+ __u32 MaxSocTemp, __u32 cf_err, __u32 scCurrentTemp, __u32 scMaxTem)
+{
+ struct json_object *root;
+ root = json_create_object();
+
+ json_object_add_value_int(root, "Current temperature", temperature);
+ json_object_add_value_int(root, "Current PCB temperature", PcbTemp);
+ json_object_add_value_int(root, "Current SOC temperature", SocTemp);
+ json_object_add_value_int(root, "Highest temperature", maxTemperature);
+ json_object_add_value_int(root, "Max SOC temperature", MaxSocTemp);
+ if (!cf_err) {
+ json_object_add_value_int(root, "SuperCap Current temperature", scCurrentTemp);
+ json_object_add_value_int(root, "SuperCap Max temperature", scMaxTem);
+ }
+
+ json_print_object(root, NULL);
+}
+
+static int temp_stats(int argc, char **argv, struct command *cmd, struct plugin *plugin)
+{
+ struct nvme_smart_log smart_log;
+ EXTENDED_SMART_INFO_T ExtdSMARTInfo;
+ vendor_log_page_CF logPageCF;
+
+ int err, cf_err;
+ int index;
+ const char *desc = "Retrieve Seagate Temperature Stats information for the given device ";
+ const char *output_format = "output in binary format";
+ unsigned int temperature = 0, PcbTemp = 0, SocTemp = 0, scCurrentTemp = 0, scMaxTemp = 0;
+ unsigned long long maxTemperature = 0, MaxSocTemp = 0;
+ struct nvme_dev *dev;
+ struct config {
+ char *output_format;
+ };
+
+ struct config cfg = {
+ .output_format = "normal",
+ };
+
+ OPT_ARGS(opts) = {
+ OPT_FMT("output-format", 'o', &cfg.output_format, output_format),
+ OPT_END()
+ };
+
+ err = parse_and_open(&dev, argc, argv, desc, opts);
+ if (err) {
+ printf ("\nDevice not found \n");;
+ return -1;
+ }
+
+ if (strcmp(cfg.output_format, "json"))
+ printf("Seagate Temperature Stats Information :\n");
+ /*STEP-1 : Get Current Temperature from SMART */
+ err = nvme_get_log_smart(dev_fd(dev), 0xffffffff, false, &smart_log);
+ if (!err) {
+ temperature = ((smart_log.temperature[1] << 8) | smart_log.temperature[0]);
+ temperature = temperature ? temperature - 273 : 0;
+ PcbTemp = le16_to_cpu(smart_log.temp_sensor[0]);
+ PcbTemp = PcbTemp ? PcbTemp - 273 : 0;
+ SocTemp = le16_to_cpu(smart_log.temp_sensor[1]);
+ SocTemp = SocTemp ? SocTemp - 273 : 0;
+ if (strcmp(cfg.output_format, "json")) {
+ printf("%-20s : %u C\n", "Current Temperature", temperature);
+ printf("%-20s : %u C\n", "Current PCB Temperature", PcbTemp);
+ printf("%-20s : %u C\n", "Current SOC Temperature", SocTemp);
+ }
+ }
+
+ /* STEP-2 : Get Max temperature form Ext SMART-id 194 */
+ err = nvme_get_log_simple(dev_fd(dev), 0xC4,
+ sizeof(ExtdSMARTInfo), &ExtdSMARTInfo);
+ if (!err) {
+ for (index = 0; index < NUMBER_EXTENDED_SMART_ATTRIBUTES; index++) {
+ if (ExtdSMARTInfo.vendorData[index].AttributeNumber == VS_ATTR_ID_MAX_LIFE_TEMPERATURE) {
+ maxTemperature = smart_attribute_vs(ExtdSMARTInfo.Version, ExtdSMARTInfo.vendorData[index]);
+ maxTemperature = maxTemperature ? maxTemperature - 273 : 0;
+ if (strcmp(cfg.output_format, "json"))
+ printf("%-20s : %d C\n", "Highest Temperature", (unsigned int)maxTemperature);
+ }
+
+ if (ExtdSMARTInfo.vendorData[index].AttributeNumber == VS_ATTR_ID_MAX_SOC_LIFE_TEMPERATURE) {
+ MaxSocTemp = smart_attribute_vs(ExtdSMARTInfo.Version, ExtdSMARTInfo.vendorData[index]);
+ MaxSocTemp = MaxSocTemp ? MaxSocTemp - 273 : 0;
+ if (strcmp(cfg.output_format, "json"))
+ printf("%-20s : %d C\n", "Max SOC Temperature", (unsigned int)MaxSocTemp);
+ }
+ }
+ } else {
+ if (err > 0)
+ nvme_show_status(err);
+ }
+
+ cf_err = nvme_get_log_simple(dev_fd(dev), 0xCF,
+ sizeof(ExtdSMARTInfo), &logPageCF);
+
+ if (!cf_err) {
+ scCurrentTemp = logPageCF.AttrCF.SuperCapCurrentTemperature;
+ scCurrentTemp = scCurrentTemp ? scCurrentTemp - 273 : 0;
+ printf("%-20s : %d C\n", "Super-cap Current Temperature", scCurrentTemp);
+
+ scMaxTemp = logPageCF.AttrCF.SuperCapMaximumTemperature;
+ scMaxTemp = scMaxTemp ? scMaxTemp - 273 : 0;
+ printf("%-20s : %d C\n", "Super-cap Max Temperature", scMaxTemp);
+ }
+
+ if (!strcmp(cfg.output_format, "json"))
+ json_temp_stats(temperature, PcbTemp, SocTemp, maxTemperature, MaxSocTemp, cf_err, scCurrentTemp, scMaxTemp);
+
+ dev_close(dev);
+ return err;
+}
+/* EOF Temperature Stats information */
+
+/***************************************
+ * PCIe error-log information
+ ***************************************/
+static void print_vs_pcie_error_log(pcie_error_log_page pcieErrorLog)
+{
+ __u32 correctPcieEc = 0;
+ __u32 uncorrectPcieEc = 0;
+ correctPcieEc = pcieErrorLog.BadDllpErrCnt + pcieErrorLog.BadTlpErrCnt
+ + pcieErrorLog.RcvrErrCnt + pcieErrorLog.ReplayTOErrCnt
+ + pcieErrorLog.ReplayNumRolloverErrCnt;
+
+ uncorrectPcieEc = pcieErrorLog.FCProtocolErrCnt + pcieErrorLog.DllpProtocolErrCnt
+ + pcieErrorLog.CmpltnTOErrCnt + pcieErrorLog.RcvrQOverflowErrCnt
+ + pcieErrorLog.UnexpectedCplTlpErrCnt + pcieErrorLog.CplTlpURErrCnt
+ + pcieErrorLog.CplTlpCAErrCnt + pcieErrorLog.ReqCAErrCnt
+ + pcieErrorLog.ReqURErrCnt + pcieErrorLog.EcrcErrCnt
+ + pcieErrorLog.MalformedTlpErrCnt + pcieErrorLog.CplTlpPoisonedErrCnt
+ + pcieErrorLog.MemRdTlpPoisonedErrCnt;
+
+ printf("%-45s : %u\n", "PCIe Correctable Error Count", correctPcieEc);
+ printf("%-45s : %u\n", "PCIe Un-Correctable Error Count", uncorrectPcieEc);
+ printf("%-45s : %u\n", "Unsupported Request Error Status (URES)", pcieErrorLog.ReqURErrCnt);
+ printf("%-45s : %u\n", "ECRC Error Status (ECRCES)", pcieErrorLog.EcrcErrCnt);
+ printf("%-45s : %u\n", "Malformed TLP Status (MTS)", pcieErrorLog.MalformedTlpErrCnt);
+ printf("%-45s : %u\n", "Receiver Overflow Status (ROS)", pcieErrorLog.RcvrQOverflowErrCnt);
+ printf("%-45s : %u\n", "Unexpected Completion Status(UCS)", pcieErrorLog.UnexpectedCplTlpErrCnt);
+ printf("%-45s : %u\n", "Completion Timeout Status (CTS)", pcieErrorLog.CmpltnTOErrCnt);
+ printf("%-45s : %u\n", "Flow Control Protocol Error Status (FCPES)", pcieErrorLog.FCProtocolErrCnt);
+ printf("%-45s : %u\n", "Poisoned TLP Status (PTS)", pcieErrorLog.MemRdTlpPoisonedErrCnt);
+ printf("%-45s : %u\n", "Data Link Protocol Error Status(DLPES)", pcieErrorLog.DllpProtocolErrCnt);
+ printf("%-45s : %u\n", "Replay Timer Timeout Status(RTS)", pcieErrorLog.ReplayTOErrCnt);
+ printf("%-45s : %u\n", "Replay_NUM Rollover Status(RRS)", pcieErrorLog.ReplayNumRolloverErrCnt);
+ printf("%-45s : %u\n", "Bad DLLP Status (BDS)", pcieErrorLog.BadDllpErrCnt);
+ printf("%-45s : %u\n", "Bad TLP Status (BTS)", pcieErrorLog.BadTlpErrCnt);
+ printf("%-45s : %u\n", "Receiver Error Status (RES)", pcieErrorLog.RcvrErrCnt);
+ printf("%-45s : %u\n", "Cpl TLP Unsupported Request Error Count", pcieErrorLog.CplTlpURErrCnt);
+ printf("%-45s : %u\n", "Cpl TLP Completion Abort Error Count", pcieErrorLog.CplTlpCAErrCnt);
+ printf("%-45s : %u\n", "Cpl TLP Poisoned Error Count", pcieErrorLog.CplTlpPoisonedErrCnt);
+ printf("%-45s : %u\n", "Request Completion Abort Error Count", pcieErrorLog.ReqCAErrCnt);
+ printf("%-45s : %s\n", "Advisory Non-Fatal Error Status(ANFES)", "Not Supported");
+ printf("%-45s : %s\n", "Completer Abort Status (CAS)", "Not Supported");
+}
+
+static void json_vs_pcie_error_log(pcie_error_log_page pcieErrorLog)
+{
+ struct json_object *root;
+ root = json_create_object();
+ __u32 correctPcieEc = 0;
+ __u32 uncorrectPcieEc = 0;
+ correctPcieEc = pcieErrorLog.BadDllpErrCnt + pcieErrorLog.BadTlpErrCnt
+ + pcieErrorLog.RcvrErrCnt + pcieErrorLog.ReplayTOErrCnt
+ + pcieErrorLog.ReplayNumRolloverErrCnt;
+
+ uncorrectPcieEc = pcieErrorLog.FCProtocolErrCnt + pcieErrorLog.DllpProtocolErrCnt
+ + pcieErrorLog.CmpltnTOErrCnt + pcieErrorLog.RcvrQOverflowErrCnt
+ + pcieErrorLog.UnexpectedCplTlpErrCnt + pcieErrorLog.CplTlpURErrCnt
+ + pcieErrorLog.CplTlpCAErrCnt + pcieErrorLog.ReqCAErrCnt
+ + pcieErrorLog.ReqURErrCnt + pcieErrorLog.EcrcErrCnt
+ + pcieErrorLog.MalformedTlpErrCnt + pcieErrorLog.CplTlpPoisonedErrCnt
+ + pcieErrorLog.MemRdTlpPoisonedErrCnt;
+
+ json_object_add_value_int(root, "PCIe Correctable Error Count", correctPcieEc);
+ json_object_add_value_int(root, "PCIe Un-Correctable Error Count", uncorrectPcieEc);
+ json_object_add_value_int(root, "Unsupported Request Error Status (URES)", pcieErrorLog.ReqURErrCnt);
+ json_object_add_value_int(root, "ECRC Error Status (ECRCES)", pcieErrorLog.EcrcErrCnt);
+ json_object_add_value_int(root, "Malformed TLP Status (MTS)", pcieErrorLog.MalformedTlpErrCnt);
+ json_object_add_value_int(root, "Receiver Overflow Status (ROS)", pcieErrorLog.RcvrQOverflowErrCnt);
+ json_object_add_value_int(root, "Unexpected Completion Status(UCS)", pcieErrorLog.UnexpectedCplTlpErrCnt);
+ json_object_add_value_int(root, "Completion Timeout Status (CTS)", pcieErrorLog.CmpltnTOErrCnt);
+ json_object_add_value_int(root, "Flow Control Protocol Error Status (FCPES)", pcieErrorLog.FCProtocolErrCnt);
+ json_object_add_value_int(root, "Poisoned TLP Status (PTS)", pcieErrorLog.MemRdTlpPoisonedErrCnt);
+ json_object_add_value_int(root, "Data Link Protocol Error Status(DLPES)", pcieErrorLog.DllpProtocolErrCnt);
+ json_object_add_value_int(root, "Replay Timer Timeout Status(RTS)", pcieErrorLog.ReplayTOErrCnt);
+ json_object_add_value_int(root, "Replay_NUM Rollover Status(RRS)", pcieErrorLog.ReplayNumRolloverErrCnt);
+ json_object_add_value_int(root, "Bad DLLP Status (BDS)", pcieErrorLog.BadDllpErrCnt);
+ json_object_add_value_int(root, "Bad TLP Status (BTS)", pcieErrorLog.BadTlpErrCnt);
+ json_object_add_value_int(root, "Receiver Error Status (RES)", pcieErrorLog.RcvrErrCnt);
+ json_object_add_value_int(root, "Cpl TLP Unsupported Request Error Count", pcieErrorLog.CplTlpURErrCnt);
+ json_object_add_value_int(root, "Cpl TLP Completion Abort Error Count", pcieErrorLog.CplTlpCAErrCnt);
+ json_object_add_value_int(root, "Cpl TLP Poisoned Error Count", pcieErrorLog.CplTlpPoisonedErrCnt);
+ json_object_add_value_int(root, "Request Completion Abort Error Count", pcieErrorLog.ReqCAErrCnt);
+ json_print_object(root, NULL);
+}
+
+static int vs_pcie_error_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
+{
+ pcie_error_log_page pcieErrorLog;
+ struct nvme_dev *dev;
+
+ const char *desc = "Retrieve Seagate PCIe error counters for the given device ";
+ const char *output_format = "output in binary format";
+ int err;
+ struct config {
+ char *output_format;
+ };
+
+ struct config cfg = {
+ .output_format = "normal",
+ };
+
+ OPT_ARGS(opts) = {
+ OPT_FMT("output-format", 'o', &cfg.output_format, output_format),
+ OPT_END()
+ };
+
+ err = parse_and_open(&dev, argc, argv, desc, opts);
+ if (err) {
+ printf ("\nDevice not found \n");;
+ return -1;
+ }
+
+ if (strcmp(cfg.output_format, "json"))
+ printf("Seagate PCIe error counters Information :\n");
+
+ err = nvme_get_log_simple(dev_fd(dev), 0xCB,
+ sizeof(pcieErrorLog), &pcieErrorLog);
+ if (!err) {
+ if (strcmp(cfg.output_format, "json")) {
+ print_vs_pcie_error_log(pcieErrorLog);
+ } else
+ json_vs_pcie_error_log(pcieErrorLog);
+
+ } else if (err > 0)
+ nvme_show_status(err);
+
+ dev_close(dev);
+ return err;
+}
+/* EOF PCIE error-log information */
+
+
+/***************************************
+ * FW Activation History log
+ ***************************************/
+static void print_stx_vs_fw_activate_history(stx_fw_activ_history_log_page fwActivHis)
+{
+ __u32 i;
+ char prev_fw[9] = {0};
+ char new_fw[9] = {0};
+ char buf[80];
+
+ if (fwActivHis.numValidFwActHisEnt > 0) {
+ printf("\n\nSeagate FW Activation Histry :\n");
+ printf("%-9s %-21s %-7s %-13s %-9s %-5s %-15s %-9s\n", "Counter ", " Timestamp ", " PCC ", "Previous FW ", "New FW ", "Slot", "Commit Action", "Result");
+
+ for (i = 0; i < fwActivHis.numValidFwActHisEnt; i++) {
+
+ printf(" %-4d ", fwActivHis.fwActHisEnt[i].fwActivCnt);
+
+ time_t t = fwActivHis.fwActHisEnt[i].timeStamp / 1000;
+ struct tm ts;
+ ts = *localtime(&t);
+ strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &ts);
+ printf(" %-20s ", buf);
+ printf("%-5" PRId64 " ",
+ (uint64_t)fwActivHis.fwActHisEnt[i].powCycleCnt);
+
+ memset(prev_fw, 0, sizeof(prev_fw));
+ memcpy(prev_fw, fwActivHis.fwActHisEnt[i].previousFW, sizeof(fwActivHis.fwActHisEnt[i].previousFW));
+ printf("%-8s ", prev_fw);
+
+ memset(new_fw, 0, sizeof(new_fw));
+ memcpy(new_fw, fwActivHis.fwActHisEnt[i].newFW, sizeof(fwActivHis.fwActHisEnt[i].newFW));
+ printf("%-8s ", new_fw);
+
+ printf(" %-2d ", fwActivHis.fwActHisEnt[i].slotNum);
+ printf(" 0x%02x ", fwActivHis.fwActHisEnt[i].commitActionType);
+ printf(" 0x%02x \n", fwActivHis.fwActHisEnt[i].result);
+ }
+ } else {
+ printf("%s\n", "Do not have valid FW Activation History");
+ }
+}
+
+static void json_stx_vs_fw_activate_history(stx_fw_activ_history_log_page fwActivHis)
+{
+ struct json_object *root;
+ root = json_create_object();
+ __u32 i;
+
+ char buf[80];
+
+ struct json_object *historyLogPage;
+ historyLogPage = json_create_array();
+ json_object_add_value_array(root, "Seagate FW Activation History", historyLogPage);
+
+ if (fwActivHis.numValidFwActHisEnt > 0) {
+ for (i = 0; i < fwActivHis.numValidFwActHisEnt; i++) {
+ struct json_object *lbaf = json_create_object();
+ char prev_fw[8] = { 0 };
+ char new_fw[8] = { 0 };
+
+ json_object_add_value_int(lbaf, "Counter", fwActivHis.fwActHisEnt[i].fwActivCnt);
+
+ time_t t = fwActivHis.fwActHisEnt[i].timeStamp / 1000;
+ struct tm ts;
+ ts = *localtime(&t);
+ strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &ts);
+ printf(" %-20s ", buf);
+ json_object_add_value_string(lbaf, "Timestamp", buf);
+
+ json_object_add_value_int(lbaf, "PCC", fwActivHis.fwActHisEnt[i].powCycleCnt);
+ sprintf(prev_fw, "%s", fwActivHis.fwActHisEnt[i].previousFW);
+ json_object_add_value_string(lbaf, "Previous_FW", prev_fw);
+
+ sprintf(new_fw, "%s", fwActivHis.fwActHisEnt[i].newFW);
+ json_object_add_value_string(lbaf, "New_FW", new_fw);
+
+ json_object_add_value_int(lbaf, "Slot", fwActivHis.fwActHisEnt[i].slotNum);
+ json_object_add_value_int(lbaf, "Commit_Action", fwActivHis.fwActHisEnt[i].commitActionType);
+ json_object_add_value_int(lbaf, "Result", fwActivHis.fwActHisEnt[i].result);
+
+ json_array_add_value_object(historyLogPage, lbaf);
+ }
+ } else {
+ printf("%s\n", "Do not have valid FW Activation History");
+ }
+
+ json_print_object(root, NULL);
+ json_free_object(root);
+}
+
+static int stx_vs_fw_activate_history(int argc, char **argv, struct command *cmd, struct plugin *plugin)
+{
+ stx_fw_activ_history_log_page fwActivHis;
+ struct nvme_dev *dev;
+
+ const char *desc = "Retrieve FW Activate History for Seagate device ";
+ const char *output_format = "output in binary format";
+ int err;
+ struct config {
+ char *output_format;
+ };
+
+ struct config cfg = {
+ .output_format = "normal",
+ };
+
+ OPT_ARGS(opts) = {
+ OPT_FMT("output-format", 'o', &cfg.output_format, output_format),
+ OPT_END()
+ };
+
+ err = parse_and_open(&dev, argc, argv, desc, opts);
+ if (err < 0) {
+ printf ("\nDevice not found \n");;
+ return -1;
+ }
+
+ if (strcmp(cfg.output_format, "json"))
+ printf("Seagate FW Activation Histry Information :\n");
+
+ err = nvme_get_log_simple(dev_fd(dev), 0xC2, sizeof(fwActivHis), &fwActivHis);
+ if (!err) {
+ if (strcmp(cfg.output_format, "json")) {
+ print_stx_vs_fw_activate_history(fwActivHis);
+ } else
+ json_stx_vs_fw_activate_history(fwActivHis);
+
+ } else if (err > 0)
+ nvme_show_status(err);
+
+ dev_close(dev);
+ return err;
+}
+/* EOF FW Activation History log information */
+
+
+static int clear_fw_activate_history(int argc, char **argv, struct command *cmd, struct plugin *plugin)
+{
+ const char *desc = "Clear FW Activation History for the given Seagate device ";
+ const char *save = "specifies that the controller shall save the attribute";
+ int err;
+ struct nvme_dev *dev;
+ struct nvme_id_ctrl ctrl;
+ char modelNo[40];
+ __u32 result;
+
+ struct config {
+ bool save;
+ };
+
+ struct config cfg = {
+ .save = 0,
+ };
+
+ OPT_ARGS(opts) = {
+ OPT_FLAG("save", 's', &cfg.save, save),
+ OPT_END()
+ };
+
+ err = parse_and_open(&dev, argc, argv, desc, opts);
+ if (err < 0) {
+ printf ("\nDevice not found \n");
+ return -1;
+ }
+
+ err = nvme_identify_ctrl(dev_fd(dev), &ctrl);
+ if (!err) {
+ memcpy(modelNo, ctrl.mn, sizeof(modelNo));
+ } else {
+ nvme_show_status(err);
+ return err;
+ }
+
+ if (stx_is_jag_pan(modelNo) == 0) {
+ printf ("\nDevice does not support Clear FW Activation History \n");
+ } else {
+
+ struct nvme_set_features_args args = {
+ .args_size = sizeof(args),
+ .fd = dev_fd(dev),
+ .fid = 0xC1,
+ .nsid = 0,
+ .cdw11 = 0x80000000,
+ .cdw12 = 0,
+ .save = 0,
+ .uuidx = 0,
+ .cdw15 = 0,
+ .data_len = 0,
+ .data = NULL,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = &result,
+ };
+ err = nvme_set_features(&args);
+ if (err)
+ fprintf(stderr, "%s: couldn't clear PCIe correctable errors \n",
+ __func__);
+ }
+
+ if (err < 0) {
+ perror("set-feature");
+ return errno;
+ }
+
+ dev_close(dev);
+ return err;
+}
+
+
+static int vs_clr_pcie_correctable_errs(int argc, char **argv, struct command *cmd, struct plugin *plugin)
+{
+ const char *desc = "Clear Seagate PCIe Correctable counters for the given device ";
+ const char *save = "specifies that the controller shall save the attribute";
+
+ struct nvme_id_ctrl ctrl;
+ char modelNo[40];
+
+ struct nvme_dev *dev;
+
+ __u32 result;
+ int err;
+
+ struct config {
+ bool save;
+ };
+
+ struct config cfg = {
+ .save = 0,
+ };
+
+ OPT_ARGS(opts) = {
+ OPT_FLAG("save", 's', &cfg.save, save),
+ OPT_END()
+ };
+
+ err = parse_and_open(&dev, argc, argv, desc, opts);
+ if (err) {
+ printf ("\nDevice not found \n");;
+ return -1;
+ }
+
+
+ err = nvme_identify_ctrl(dev_fd(dev), &ctrl);
+ if (!err) {
+ memcpy(modelNo, ctrl.mn, sizeof(modelNo));
+ } else {
+ nvme_show_status(err);
+ return err;
+ }
+
+ if (stx_is_jag_pan(modelNo) == 0) {
+ err = nvme_set_features_simple(dev_fd(dev), 0xE1, 0, 0xCB, cfg.save, &result);
+ } else {
+ struct nvme_set_features_args args = {
+ .args_size = sizeof(args),
+ .fd = dev_fd(dev),
+ .fid = 0xC3,
+ .nsid = 0,
+ .cdw11 = 0x80000000,
+ .cdw12 = 0,
+ .save = 0,
+ .uuidx = 0,
+ .cdw15 = 0,
+ .data_len = 0,
+ .data = NULL,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = &result,
+ };
+ err = nvme_set_features(&args);
+ if (err)
+ fprintf(stderr, "%s: couldn't clear PCIe correctable errors \n", __func__);
+ }
+
+ err = nvme_set_features_simple(dev_fd(dev), 0xE1, 0, 0xCB, cfg.save, &result);
+
+ if (err < 0) {
+ perror("set-feature");
+ return errno;
+ }
+
+ dev_close(dev);
+ return err;
+}
+
+static int get_host_tele(int argc, char **argv, struct command *cmd, struct plugin *plugin)
+{
+ const char *desc = "Capture the Telemetry Host-Initiated Data in either " \
+ "hex-dump (default) or binary format";
+ const char *namespace_id = "desired namespace";
+ const char *log_specific = "1 - controller shall capture Data representing the internal " \
+ "state of the controller at the time the command is processed. " \
+ "0 - controller shall not update the Telemetry Host Initiated Data.";
+ const char *raw = "output in raw format";
+ struct nvme_temetry_log_hdr tele_log;
+ int blkCnt, maxBlk = 0, blksToGet;
+ struct nvme_dev *dev;
+ unsigned char *log;
+ __le64 offset = 0;
+ int err, dump_fd;
+
+ struct config {
+ __u32 namespace_id;
+ __u32 log_id;
+ bool raw_binary;
+ };
+
+ struct config cfg = {
+ .namespace_id = 0xffffffff,
+ .log_id = 0,
+ };
+
+ OPT_ARGS(opts) = {
+ OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id),
+ OPT_UINT("log_specific", 'i', &cfg.log_id, log_specific),
+ OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw),
+ OPT_END()
+ };
+
+ err = parse_and_open(&dev, argc, argv, desc, opts);
+ if (err)
+ return err;
+
+ dump_fd = STDOUT_FILENO;
+ cfg.log_id = (cfg.log_id << 8) | 0x07;
+ err = nvme_get_nsid_log(dev_fd(dev), false, cfg.log_id,
+ cfg.namespace_id,
+ sizeof(tele_log), (void *)(&tele_log));
+ if (!err) {
+ maxBlk = tele_log.tele_data_area3;
+ offset += 512;
+
+ if (!cfg.raw_binary) {
+ printf("Device:%s log-id:%d namespace-id:%#x\n",
+ dev->name, cfg.log_id,
+ cfg.namespace_id);
+ printf("Data Block 1 Last Block:%d Data Block 2 Last Block:%d Data Block 3 Last Block:%d\n",
+ tele_log.tele_data_area1, tele_log.tele_data_area2, tele_log.tele_data_area3);
+
+ d((unsigned char *)(&tele_log), sizeof(tele_log), 16, 1);
+ } else
+ seaget_d_raw((unsigned char *)(&tele_log), sizeof(tele_log), dump_fd);
+ } else if (err > 0)
+ nvme_show_status(err);
+ else
+ perror("log page");
+
+ blkCnt = 0;
+
+ while (blkCnt < maxBlk) {
+ unsigned long long bytesToGet;
+
+ blksToGet = ((maxBlk - blkCnt) >= TELEMETRY_BLOCKS_TO_READ) ? TELEMETRY_BLOCKS_TO_READ : (maxBlk - blkCnt);
+
+ if (blksToGet == 0) {
+ dev_close(dev);
+ return err;
+ }
+
+ bytesToGet = (unsigned long long)blksToGet * 512;
+ log = malloc(bytesToGet);
+
+ if (!log) {
+ fprintf(stderr, "could not alloc buffer for log\n");
+ dev_close(dev);
+ return EINVAL;
+ }
+
+ memset(log, 0, bytesToGet);
+
+ struct nvme_get_log_args args = {
+ .args_size = sizeof(args),
+ .fd = dev_fd(dev),
+ .lid = cfg.log_id,
+ .nsid = cfg.namespace_id,
+ .lpo = offset,
+ .lsp = 0,
+ .lsi = 0,
+ .rae = true,
+ .uuidx = 0,
+ .csi = NVME_CSI_NVM,
+ .ot = false,
+ .len = bytesToGet,
+ .log = (void *)log,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = NULL,
+ };
+ err = nvme_get_log(&args);
+ if (!err) {
+ offset += (__le64)bytesToGet;
+
+ if (!cfg.raw_binary) {
+ printf("\nBlock # :%d to %d\n", blkCnt + 1, blkCnt + blksToGet);
+
+ d((unsigned char *)log, bytesToGet, 16, 1);
+ } else
+ seaget_d_raw((unsigned char *)log, bytesToGet, dump_fd);
+ } else if (err > 0)
+ nvme_show_status(err);
+ else
+ perror("log page");
+
+ blkCnt += blksToGet;
+
+ free(log);
+ }
+
+ dev_close(dev);
+ return err;
+}
+
+static int get_ctrl_tele(int argc, char **argv, struct command *cmd, struct plugin *plugin)
+{
+ const char *desc = "Capture the Telemetry Controller-Initiated Data in either " \
+ "hex-dump (default) or binary format";
+ const char *namespace_id = "desired namespace";
+ const char *raw = "output in raw format";
+ struct nvme_dev *dev;
+ int err, dump_fd;
+ struct nvme_temetry_log_hdr tele_log;
+ __le64 offset = 0;
+ __u16 log_id;
+ int blkCnt, maxBlk = 0, blksToGet;
+ unsigned char *log;
+
+ struct config {
+ __u32 namespace_id;
+ bool raw_binary;
+ };
+
+ struct config cfg = {
+ .namespace_id = 0xffffffff,
+ };
+
+ OPT_ARGS(opts) = {
+ OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id),
+ OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw),
+ OPT_END()
+ };
+
+ err = parse_and_open(&dev, argc, argv, desc, opts);
+ if (err)
+ return err;
+
+ dump_fd = STDOUT_FILENO;
+
+ log_id = 0x08;
+ err = nvme_get_nsid_log(dev_fd(dev), false, log_id, cfg.namespace_id,
+ sizeof(tele_log), (void *)(&tele_log));
+ if (!err) {
+ maxBlk = tele_log.tele_data_area3;
+ offset += 512;
+
+ if (!cfg.raw_binary) {
+ printf("Device:%s namespace-id:%#x\n",
+ dev->name, cfg.namespace_id);
+ printf("Data Block 1 Last Block:%d Data Block 2 Last Block:%d Data Block 3 Last Block:%d\n",
+ tele_log.tele_data_area1, tele_log.tele_data_area2, tele_log.tele_data_area3);
+
+ d((unsigned char *)(&tele_log), sizeof(tele_log), 16, 1);
+ } else
+ seaget_d_raw((unsigned char *)(&tele_log), sizeof(tele_log), dump_fd);
+ } else if (err > 0)
+ nvme_show_status(err);
+ else
+ perror("log page");
+
+ blkCnt = 0;
+
+ while (blkCnt < maxBlk) {
+ unsigned long long bytesToGet;
+
+ blksToGet = ((maxBlk - blkCnt) >= TELEMETRY_BLOCKS_TO_READ) ? TELEMETRY_BLOCKS_TO_READ : (maxBlk - blkCnt);
+
+ if (blksToGet == 0)
+ return err;
+
+ bytesToGet = (unsigned long long)blksToGet * 512;
+ log = malloc(bytesToGet);
+
+ if (!log) {
+ fprintf(stderr, "could not alloc buffer for log\n");
+ return EINVAL;
+ }
+
+ memset(log, 0, bytesToGet);
+
+ struct nvme_get_log_args args = {
+ .args_size = sizeof(args),
+ .fd = dev_fd(dev),
+ .lid = log_id,
+ .nsid = cfg.namespace_id,
+ .lpo = offset,
+ .lsp = 0,
+ .lsi = 0,
+ .rae = true,
+ .uuidx = 0,
+ .csi = NVME_CSI_NVM,
+ .ot = false,
+ .len = bytesToGet,
+ .log = (void *)log,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = NULL,
+ };
+ err = nvme_get_log(&args);
+ if (!err) {
+ offset += (__le64)bytesToGet;
+
+ if (!cfg.raw_binary) {
+ printf("\nBlock # :%d to %d\n", blkCnt + 1, blkCnt + blksToGet);
+
+ d((unsigned char *)log, bytesToGet, 16, 1);
+ } else
+ seaget_d_raw((unsigned char *)log, bytesToGet, dump_fd);
+ } else if (err > 0)
+ nvme_show_status(err);
+ else
+ perror("log page");
+
+ blkCnt += blksToGet;
+
+ free(log);
+ }
+
+ dev_close(dev);
+ return err;
+}
+
+void seaget_d_raw(unsigned char *buf, int len, int fd)
+{
+ if (write(fd, (void *)buf, len) <= 0)
+ printf("%s: Write Failed\n", __FUNCTION__);
+}
+
+
+static int vs_internal_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
+{
+ const char *desc = "Capture the Telemetry Controller-Initiated Data in " \
+ "binary format";
+ const char *namespace_id = "desired namespace";
+
+ const char *file = "dump file";
+ struct nvme_dev *dev;
+ int err, dump_fd;
+ int flags = O_WRONLY | O_CREAT;
+ int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH;
+ struct nvme_temetry_log_hdr tele_log;
+ __le64 offset = 0;
+ __u16 log_id;
+ int blkCnt, maxBlk = 0, blksToGet;
+ unsigned char *log;
+
+ struct config {
+ __u32 namespace_id;
+ char *file;
+ };
+
+ struct config cfg = {
+ .namespace_id = 0xffffffff,
+ .file = "",
+ };
+
+ OPT_ARGS(opts) = {
+ OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id),
+ OPT_FILE("dump-file", 'f', &cfg.file, file),
+ OPT_END()
+ };
+
+ err = parse_and_open(&dev, argc, argv, desc, opts);
+ if (err)
+ return err;
+
+ dump_fd = STDOUT_FILENO;
+ if (strlen(cfg.file)) {
+ dump_fd = open(cfg.file, flags, mode);
+ if (dump_fd < 0) {
+ perror(cfg.file);
+ dev_close(dev);
+ return EINVAL;
+ }
+ }
+
+ log_id = 0x08;
+ err = nvme_get_nsid_log(dev_fd(dev), false, log_id, cfg.namespace_id,
+ sizeof(tele_log), (void *)(&tele_log));
+ if (!err) {
+ maxBlk = tele_log.tele_data_area3;
+ offset += 512;
+
+ seaget_d_raw((unsigned char *)(&tele_log), sizeof(tele_log), dump_fd);
+ } else if (err > 0)
+ nvme_show_status(err);
+ else
+ perror("log page");
+
+ blkCnt = 0;
+
+ while (blkCnt < maxBlk) {
+ unsigned long long bytesToGet;
+
+ blksToGet = ((maxBlk - blkCnt) >= TELEMETRY_BLOCKS_TO_READ) ? TELEMETRY_BLOCKS_TO_READ : (maxBlk - blkCnt);
+
+ if (blksToGet == 0) {
+ goto out;
+ }
+
+ bytesToGet = (unsigned long long)blksToGet * 512;
+ log = malloc(bytesToGet);
+
+ if (!log) {
+ fprintf(stderr, "could not alloc buffer for log\n");
+ err = EINVAL;
+ goto out;
+ }
+
+ memset(log, 0, bytesToGet);
+
+ struct nvme_get_log_args args = {
+ .args_size = sizeof(args),
+ .fd = dev_fd(dev),
+ .lid = log_id,
+ .nsid = cfg.namespace_id,
+ .lpo = offset,
+ .lsp = 0,
+ .lsi = 0,
+ .rae = true,
+ .uuidx = 0,
+ .csi = NVME_CSI_NVM,
+ .ot = false,
+ .len = bytesToGet,
+ .log = (void *)log,
+ .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+ .result = NULL,
+ };
+ err = nvme_get_log(&args);
+ if (!err) {
+ offset += (__le64)bytesToGet;
+
+ seaget_d_raw((unsigned char *)log, bytesToGet, dump_fd);
+
+ } else if (err > 0)
+ nvme_show_status(err);
+ else
+ perror("log page");
+
+ blkCnt += blksToGet;
+
+ free(log);
+ }
+out:
+ if (strlen(cfg.file))
+ close(dump_fd);
+
+ dev_close(dev);
+ return err;
+}
+
+/*SEAGATE-PLUGIN Version */
+static int seagate_plugin_version(int argc, char **argv, struct command *cmd, struct plugin *plugin)
+{
+ printf("Seagate-Plugin version : %d.%d \n",
+ SEAGATE_PLUGIN_VERSION_MAJOR,
+ SEAGATE_PLUGIN_VERSION_MINOR);
+ return 0;
+}
+/*EOF SEAGATE-PLUGIN Version */
+
+/*OCP SEAGATE-PLUGIN Version */
+static int stx_ocp_plugin_version(int argc, char **argv, struct command *cmd, struct plugin *plugin)
+{
+ printf("Seagate-OCP-Plugin version : %d.%d \n",
+ SEAGATE_OCP_PLUGIN_VERSION_MAJOR,
+ SEAGATE_OCP_PLUGIN_VERSION_MINOR);
+ return 0;
+}
+/*EOF OCP SEAGATE-PLUGIN Version */
diff --git a/plugins/seagate/seagate-nvme.h b/plugins/seagate/seagate-nvme.h
new file mode 100644
index 0000000..99f6327
--- /dev/null
+++ b/plugins/seagate/seagate-nvme.h
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Do NOT modify or remove this copyright and license
+ *
+ * Copyright (c) 2017-2018 Seagate Technology LLC and/or its Affiliates, All Rights Reserved
+ *
+ * ******************************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * \file seagate-nvme.h
+ * \brief This file defines the functions and macros to make building a nvme-cli seagate plug-in.
+ *
+ * Author: Debabrata Bardhan <debabrata.bardhan@seagate.com>
+ */
+
+#undef CMD_INC_FILE
+#define CMD_INC_FILE plugins/seagate/seagate-nvme
+
+#if !defined(SEAGATE_NVME) || defined(CMD_HEADER_MULTI_READ)
+#define SEAGATE_NVME
+
+#include "cmd.h"
+
+PLUGIN(NAME("seagate", "Seagate vendor specific extensions", NVME_VERSION),
+ COMMAND_LIST(
+ ENTRY("vs-temperature-stats", "Retrieve Seagate temperature statistics ", temp_stats)
+ ENTRY("vs-log-page-sup", "Retrieve Seagate Supported Log-pages Information ", log_pages_supp)
+ ENTRY("vs-smart-add-log", "Retrieve Seagate extended-SMART Information ", vs_smart_log)
+ ENTRY("vs-pcie-stats", "Retrieve Seagate PCIe error statistics ", vs_pcie_error_log)
+ ENTRY("clear-pcie-correctable-errors", "Clear Seagate PCIe error statistics ", vs_clr_pcie_correctable_errs)
+ ENTRY("get-host-tele", "Retrieve Seagate Host-Initiated Telemetry ", get_host_tele)
+ ENTRY("get-ctrl-tele", "Retrieve Seagate Controller-Initiated Telemetry ", get_ctrl_tele)
+ ENTRY("vs-internal-log", "Retrieve Seagate Controller-Initiated Telemetry in binary format", vs_internal_log)
+ ENTRY("vs-fw-activate-history", "Retrieve the Firmware Activation History", stx_vs_fw_activate_history)
+ ENTRY("clear-fw-activate-history", "Clear Firmware Activation History", clear_fw_activate_history)
+ ENTRY("plugin-version", "Shows Seagate plugin's version information ", seagate_plugin_version)
+ ENTRY("cloud-SSD-plugin-version", "Shows OCP Seagate plugin's version information ", stx_ocp_plugin_version)
+ )
+);
+
+#endif
+#include "define_cmd.h"