From: muhammad.ahmad@seagate.com Date: Wed, 23 May 2018 04:51:06 +0000 (-0500) Subject: Initial checkin for Seagate Plugin X-Git-Tag: v1.6~30^2~1^2~2 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=36351e2e47c42d96d8d9442ee715c5f2321a2fb9;p=users%2Fsagi%2Fnvme-cli.git Initial checkin for Seagate Plugin --- diff --git a/Makefile b/Makefile index 2e5d631d..6c8ba7ae 100644 --- a/Makefile +++ b/Makefile @@ -34,7 +34,7 @@ NVME_DPKG_VERSION=1~`lsb_release -sc` OBJS := argconfig.o suffix.o parser.o nvme-print.o nvme-ioctl.o \ nvme-lightnvm.o fabrics.o json.o plugin.o intel-nvme.o \ lnvm-nvme.o memblaze-nvme.o wdc-nvme.o wdc-utils.o nvme-models.o \ - huawei-nvme.o netapp-nvme.o toshiba-nvme.o + huawei-nvme.o netapp-nvme.o toshiba-nvme.o seagate-nvme.o nvme: nvme.c nvme.h $(OBJS) NVME-VERSION-FILE $(CC) $(CPPFLAGS) $(CFLAGS) nvme.c -o $(NVME) $(OBJS) $(LDFLAGS) diff --git a/seagate-diag.h b/seagate-diag.h new file mode 100755 index 00000000..a4eda4b3 --- /dev/null +++ b/seagate-diag.h @@ -0,0 +1,268 @@ +// +// 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. + + +#ifndef SEAGATE_NVME_H +#define SEAGATE_NVME_H + +#define SEAGATE_PLUGIN_VERSION_MAJOR 0 +#define SEAGATE_PLUGIN_VERSION_MINOR 9 + +#define PERSIST_FILE_SIZE (2764800) +#define ONE_MB (1048576) // (1024 * 1024) +#define PERSIST_CHUNK (65536) // (1024 * 64) +#define FOUR_KB (4096) + + +/*************************** +*Supported Log-Pages from FW +***************************/ + +typedef struct 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 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 +***************************/ +#pragma pack(1) +#define NUMBER_EXTENDED_SMART_ATTRIBUTES 42 + +typedef enum _EXTENDED_SMART_VERSION_ +{ + EXTENDED_SMART_VERSION_NONE, // 0 + EXTENDED_SMART_VERSION_GEN, // 1 + EXTENDED_SMART_VERSION_VENDOR1, // 2 +} EXTENDED_SMART_VERSION; + +typedef struct _SmartVendorSpecific +{ + __u8 AttributeNumber; + __u16 SmartStatus; + __u8 NominalValue; + __u8 LifetimeWorstValue; + __u32 Raw0_3; + __u8 RawHigh[3]; +} SmartVendorSpecific; + +typedef struct _EXTENDED_SMART_INFO_T +{ + __u16 Version; + SmartVendorSpecific vendorData[NUMBER_EXTENDED_SMART_ATTRIBUTES]; + __u8 vendor_specific_reserved[6]; +} EXTENDED_SMART_INFO_T; + +typedef struct vendor_smart_attribute_data +{ + __u8 AttributeNumber; // 00 + __u8 Rsvd[3]; // 01 -03 + __u32 LSDword; // 04-07 + __u32 MSDword; // 08 - 11 +} vendor_smart_attribute_data; + +struct 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 _U128 +{ + __u64 LS__u64; + __u64 MS__u64; +} U128; + +typedef struct _vendor_log_page_CF_Attr +{ + __u16 SuperCapCurrentTemperature; // 00-01 + __u16 SuperCapMaximumTemperature; // 02-03 + __u8 SuperCapStatus; // 04 + __u8 Reserved5to7[3]; // 05-07 + U128 DataUnitsReadToDramNamespace; // 08-23 + U128 DataUnitsWrittenToDramNamespace; // 24-39 + __u64 DramCorrectableErrorCount; // 40-47 + __u64 DramUncorrectableErrorCount; // 48-55 +}vendor_log_page_CF_Attr; + +typedef struct _vendor_log_page_CF +{ + vendor_log_page_CF_Attr AttrCF; + __u8 Vendor_Specific_Reserved[ 456 ]; // 56-511 +}vendor_log_page_CF; + +#pragma pack() +/* EOF Extended-SMART Information*/ + + +/************************** +* PCIE ERROR INFORMATION +**************************/ +typedef struct 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 + +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 362-372 + VS_ATTR_LIFETIME_WRITES1_TO_FLASH, // 31 374-385 + VS_ATTR_LIFETIME_WRITES0_FROM_HOST, // 32 386-397 + VS_ATTR_LIFETIME_WRITES1_FROM_HOST, // 33 398-409 + VS_ATTR_LIFETIME_READ0_FROM_HOST, // 34 410-421 + VS_ATTR_LIFETIME_READ1_FROM_HOST, // 35 422-433 + VS_ATTR_PCIE_PHY_CRC_ERROR, // 36 434-445 + VS_ATTR_BAD_BLOCK_COUNT_SYSTEM, // 37 446-457 + VS_ATTR_BAD_BLOCK_COUNT_USER, // 38 458-469 + VS_ATTR_THERMAL_THROTTLING_STATUS, // 39 470-481 + VS_ATTR_POWER_CONSUMPTION, // 40 482-493 + VS_ATTR_MAX_SOC_LIFE_TEMPERATURE, // 41 494-505 + + 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/seagate-nvme.c b/seagate-nvme.c new file mode 100755 index 00000000..4ced91e0 --- /dev/null +++ b/seagate-nvme.c @@ -0,0 +1,1500 @@ +// +// 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. + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "linux/nvme_ioctl.h" +#include "nvme.h" +#include "nvme-print.h" +#include "nvme-ioctl.h" +#include "plugin.h" +#include "argconfig.h" +#include "suffix.h" +#include "json.h" + +#define CREATE_CMD + +#include "seagate-nvme.h" +#include "seagate-diag.h" + + +/*************************************** +*Command for "log-pages-supp" +***************************************/ +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_HPE_WORK_LOAD"; + break; + case 0xD7: + return "VS_HPE_FW_SECURITY"; + break; + case 0xD8: + return "VS_HPE_REVISION"; + break; + + default: + return "UNKNOWN"; + break; + } +} + + +void json_log_pages_supp(log_page_map *logPageMap) +{ + struct json_object *root; + struct json_array *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 < logPageMap->NumLogPages; i++) { + struct json_object *lbaf = json_create_object(); + json_object_add_value_int(lbaf, "logpage_id", logPageMap->LogPageEntry[i].LogPageID); + json_object_add_value_string(lbaf, "logpage_name", log_pages_supp_print(logPageMap->LogPageEntry[i].LogPageID)); + + json_array_add_value_object(logPages, lbaf); + } + json_print_object(root, NULL); + printf("\n"); +} + +static int log_pages_supp(int argc, char **argv, struct command *cmd, struct plugin *plugin) +{ + int err = 0; + int fd = 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 config { + char *output_format; + }; + + struct config cfg = { + .output_format = "normal", + }; + + const struct argconfig_commandline_options command_line_options[] = { + {"output-format", 'o', "FMT", CFG_STRING, &cfg.output_format, required_argument, output_format }, + {0} + }; + + fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + + int fmt; + + err = nvme_get_log(fd, 1, 0xc5, sizeof(logPageMap), &logPageMap); + if (!err) { + if(strcmp(cfg.output_format,"json")) { + printf ("Seagate Supported Log-pages count :%d\n", 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 0) + fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); + + return err; +} + +//EOF Command for "log-pages-supp" + + +/*************************************** +* Extended-SMART Information +***************************************/ +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"; /*VS_ATTR_ID_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";/*VS_ATTR_ID_MAX_LIFE_TEMPERATURE for extended*/ + 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 read error count";/*VS_ATTR_ID_UNCORRECTABLE_RAISE_ERRORS*/ + 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"; + } +} + +__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; + val = attrVendor->MSDword; + val = (val << 32) | attrVendor->LSDword ; + return val; + } + + else + return attr.Raw0_3; +} + +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%016llx", smart_attribute_vs(verNo, attr)); + printf("\n"); + } + + 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%016llx%016llx", msbGbErased, lsbGbErased); + printf(" %s", buf); + printf("\n"); + + 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%016llx%016llx", msbLifWrtToFlash, lsbLifWrtToFlash); + printf(" %s", buf); + printf("\n"); + + 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%016llx%016llx", msbLifWrtFrmHost, lsbLifWrtFrmHost); + printf(" %s", buf); + printf("\n"); + + 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%016llx%016llx", msbLifRdToHost, lsbLifRdToHost); + printf(" %s", buf); + printf("\n"); + + 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%016llx%016llx", msbTrimCnt, lsbTrimCnt); + printf(" %s", buf); + printf("\n"); + + } +} + +void json_print_smart_log(struct json_object *root, EXTENDED_SMART_INFO_T* ExtdSMARTInfo ) +{ + /*struct json_object *root; */ + struct json_array *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}; + //char strBuf[35] = {0}; + + /*root = json_create_object();*/ + 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%016llx%016llx", msbGbErased, 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%016llx%016llx", msbLifWrtToFlash, 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%016llx%016llx", msbLifWrtFrmHost, 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%016llx%016llx", msbLifRdToHost, 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%016llx%016llx", msbTrimCnt, lsbTrimCnt); + json_object_add_value_string(lbaf, "attribute_value", buf); + json_array_add_value_object(lbafs, lbaf); + + /* + json_print_object(root, NULL); + printf("\n"); + */ +} + +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; + /*currentTemp = currentTemp ? currentTemp - 273 : 0;*/ + printf(" 0x%016llx", currentTemp); + printf("\n"); + + maxTemp = pLogPageCF->AttrCF.SuperCapMaximumTemperature; + /*maxTemp = maxTemp ? maxTemp - 273 : 0;*/ + printf("%-40s", "Super-cap maximum temperature"); + printf(" 0x%016llx", maxTemp); + printf("\n"); + + printf("%-40s", "Super-cap status"); + printf(" 0x%016llx", (__u64)pLogPageCF->AttrCF.SuperCapStatus); + printf("\n"); + + printf("%-40s", "Data units read to DRAM namespace"); + printf(" 0x%016llx%016llx", pLogPageCF->AttrCF.DataUnitsReadToDramNamespace.MS__u64, + pLogPageCF->AttrCF.DataUnitsReadToDramNamespace.LS__u64); + printf("\n"); + + printf("%-40s", "Data units written to DRAM namespace"); + printf(" 0x%016llx%016llx", pLogPageCF->AttrCF.DataUnitsWrittenToDramNamespace.MS__u64, + pLogPageCF->AttrCF.DataUnitsWrittenToDramNamespace.LS__u64); + printf("\n"); + + printf("%-40s", "DRAM correctable error count"); + printf(" 0x%016llx", pLogPageCF->AttrCF.DramCorrectableErrorCount); + printf("\n"); + + printf("%-40s", "DRAM uncorrectable error count"); + printf(" 0x%016llx", pLogPageCF->AttrCF.DramUncorrectableErrorCount); + printf("\n"); + +} + +void json_print_smart_log_CF(struct json_object *root, vendor_log_page_CF *pLogPageCF) +{ + /*struct json_object *root;*/ + struct json_array *logPages; + unsigned int currentTemp, maxTemp; + char buf[40]; + + /*root = json_create_object(); */ + + 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; + /*currentTemp = currentTemp ? currentTemp - 273 : 0;*/ + 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; + /*maxTemp = maxTemp ? maxTemp - 273 : 0;*/ + 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%016llx%016llx", pLogPageCF->AttrCF.DataUnitsReadToDramNamespace.MS__u64, + 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%016llx%016llx", pLogPageCF->AttrCF.DataUnitsWrittenToDramNamespace.MS__u64, + 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); + + /* + json_print_object(root, NULL); + printf("\n"); + */ +} + +static int vs_smart_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +{ + EXTENDED_SMART_INFO_T ExtdSMARTInfo; + vendor_log_page_CF logPageCF; + int fd; + struct json_object *root; + struct json_array *lbafs; + struct json_object *lbafs_ExtSmart, *lbafs_DramSmart; + root = json_create_object(); + lbafs = json_create_array(); + + const char *desc = "Retrieve Seagate Extended SMART information for the given device "; + const char *output_format = "output in binary format"; + int err, index=0; + struct config { + char *output_format; + }; + + struct config cfg = { + .output_format = "normal", + }; + + const struct argconfig_commandline_options command_line_options[] = { + {"output-format", 'o', "FMT", CFG_STRING, &cfg.output_format, required_argument, output_format }, + {0} + }; + + fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + if(strcmp(cfg.output_format,"json")) { + printf("Seagate Extended SMART Information :\n"); + } + + err = nvme_get_log(fd, 1, 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(fd, 1, 0xCF, sizeof(logPageCF), &logPageCF); + if (!err) { + if(strcmp(cfg.output_format,"json")) { + /*printf("Seagate DRAM Supercap SMART Attributes :\n");*/ + + 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) + fprintf(stderr, "NVMe Status:%s(%x)\n", + nvme_status_to_string(err), err); + + return err; +} +//EOF Extended-SMART Information + +static int vs_smart_log_wrapper(int argc, char **argv, struct command *cmd, struct plugin *plugin) +{ + return vs_smart_log(argc, argv, cmd, plugin); +} + +/*************************************** +* 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); + printf("\n"); + +} +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 fd; + 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 config { + char *output_format; + }; + + struct config cfg = { + .output_format = "normal", + }; + + const struct argconfig_commandline_options command_line_options[] = { + {"output-format", 'o', "FMT", CFG_STRING, &cfg.output_format, required_argument, output_format }, + {0} + }; + + fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + if (fd < 0) { + 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_smart_log(fd, 0xffffffff, &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(fd, 1, 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) + fprintf(stderr, "NVMe Status:%s(%x)\n", + nvme_status_to_string(err), err); + + cf_err = nvme_get_log(fd, 1, 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); + + return err; +} +//EOF Temperature Stats information + +static int temp_stats_wrapper(int argc, char **argv, struct command *cmd, struct plugin *plugin) +{ + return temp_stats(argc, argv, cmd, plugin); +} + + +/*************************************** +* PCIe error-log information +***************************************/ +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"); +} + +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); + printf("\n"); +} + +static int vs_pcie_error_log(int argc, char **argv, struct command *cmd, struct plugin *plugin) +{ + pcie_error_log_page pcieErrorLog; + int fd; + + 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", + }; + + const struct argconfig_commandline_options command_line_options[] = { + {"output-format", 'o', "FMT", CFG_STRING, &cfg.output_format, required_argument, output_format }, + {0} + }; + + fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + if(strcmp(cfg.output_format,"json")) + printf("Seagate PCIe error counters Information :\n"); + + err = nvme_get_log(fd, 1, 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) + fprintf(stderr, "NVMe Status:%s(%x)\n", nvme_status_to_string(err), err); + + return err; +} +//EOF PCIE error-log information + +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"; + int err, fd; + __u32 result; + void *buf = NULL; + + struct config { + int save; + }; + + struct config cfg = { + .save = 0, + }; + + const struct argconfig_commandline_options command_line_options[] = { + {"save", 's', "FLAG", CFG_NONE, &cfg.save, no_argument, save}, + {NULL} + }; + + fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + + err = nvme_set_feature(fd, 0, 0xE1, 0xCB, 0, cfg.save, 0, buf, &result); + + if (err < 0) { + perror("set-feature"); + return errno; + } + + return err; + +} + +static int vs_clr_pcie_correctable_errs_wrapper(int argc, char **argv, struct command *cmd, struct plugin *plugin) +{ + return vs_clr_pcie_correctable_errs(argc, argv, cmd, plugin); +} + +int nvme_get_log_with_offset(int fd, __u32 nsid, __u16 log_id, __u32 data_len, __u64 offset, void *data) +{ + struct nvme_admin_cmd cmd = { + .opcode = nvme_admin_get_log_page, + .nsid = nsid, + .addr = (__u64)(uintptr_t) data, + .data_len = data_len, + }; + __u32 numd = (data_len >> 2) - 1; + __u16 numdu = numd >> 16, numdl = numd & 0xffff; + + cmd.cdw10 = log_id | (numdl << 16); + cmd.cdw11 = numdu; + cmd.cdw12 = (__u32)(offset & 0xffffffff); + cmd.cdw13 = (__u32)((offset >> 32) & 0xffffffff); + + /*************************************************************************** + printf("nvme_get_log_with_offset Parameter Details - \n"); + printf("data_len : %d cdw10 : %x cdw11 : %x cdw12 : %x cdw13 : %x\n", cmd.data_len, cmd.cdw10, cmd.cdw11, cmd.cdw12, cmd.cdw13); + ***************************************************************************/ + return nvme_passthru_admin(fd, cmd.opcode, 0, 0, + cmd.nsid, 0, 0, + cmd.cdw10, cmd.cdw11, cmd.cdw12, + cmd.cdw13, 0, 0, + cmd.data_len, data, 0, + NULL, 100); +} + +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_binary = "output in raw format"; + int err, fd, dump_fd; + struct nvme_temetry_log_hdr tele_log; + __le64 offset = 0; + int blkCnt, maxBlk = 0, blksToGet; + unsigned char *log; + + struct config { + __u32 namespace_id; + __u32 log_id; + int raw_binary; + }; + + struct config cfg = { + .namespace_id = 0xffffffff, + .log_id = 0, + }; + + const struct argconfig_commandline_options command_line_options[] = { + {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace_id}, + {"log_specific", 'i', "NUM", CFG_POSITIVE, &cfg.log_id, required_argument, log_specific}, + {"raw-binary", 'b', "", CFG_NONE, &cfg.raw_binary, no_argument, raw_binary}, + {NULL} + }; + + fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + if (fd < 0) + return fd; + + dump_fd = STDOUT_FILENO; + + + cfg.log_id = (cfg.log_id << 8) | 0x07; + + err = nvme_get_log_with_offset(fd, cfg.namespace_id, cfg.log_id, sizeof(tele_log), offset, (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", + devicename, 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) + fprintf(stderr, "NVMe Status:%s(%x)\n", + nvme_status_to_string(err), err); + else + perror("log page"); + + blkCnt = 0; + + while(blkCnt < maxBlk) + { + blksToGet = ((maxBlk - blkCnt) >= TELEMETRY_BLOCKS_TO_READ) ? TELEMETRY_BLOCKS_TO_READ : (maxBlk - blkCnt); + + if(blksToGet == 0) { + return err; + } + + log = malloc(blksToGet * 512); + + if (!log) { + fprintf(stderr, "could not alloc buffer for log\n"); + return EINVAL; + } + + memset(log, 0, blksToGet * 512); + + err = nvme_get_log_with_offset(fd, cfg.namespace_id, cfg.log_id, blksToGet * 512, offset, (void *)log); + if (!err) { + offset += blksToGet * 512; + + if (!cfg.raw_binary) { + printf("\nBlock # :%d to %d\n", blkCnt + 1, blkCnt + blksToGet); + + d((unsigned char *)log, blksToGet * 512, 16, 1); + } else + seaget_d_raw((unsigned char *)log, blksToGet * 512, dump_fd); + } else if (err > 0) + fprintf(stderr, "NVMe Status:%s(%x)\n", + nvme_status_to_string(err), err); + else + perror("log page"); + + blkCnt += blksToGet; + + free(log); + } + + 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_binary = "output in raw format"; + int err, fd, 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; + int raw_binary; + }; + + struct config cfg = { + .namespace_id = 0xffffffff, + }; + + const struct argconfig_commandline_options command_line_options[] = { + {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace_id}, + {"raw-binary", 'b', "", CFG_NONE, &cfg.raw_binary, no_argument, raw_binary}, + {NULL} + }; + + fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + if (fd < 0) + return fd; + + dump_fd = STDOUT_FILENO; + + log_id = 0x08; + err = nvme_get_log_with_offset(fd, cfg.namespace_id, log_id, sizeof(tele_log), offset, (void *)(&tele_log)); + if (!err) { + + maxBlk = tele_log.tele_data_area3; + offset += 512; + + if (!cfg.raw_binary) { + printf("Device:%s namespace-id:%#x\n", + devicename, 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) + fprintf(stderr, "NVMe Status:%s(%x)\n", + nvme_status_to_string(err), err); + else + perror("log page"); + + blkCnt = 0; + + while(blkCnt < maxBlk) + { + blksToGet = ((maxBlk - blkCnt) >= TELEMETRY_BLOCKS_TO_READ) ? TELEMETRY_BLOCKS_TO_READ : (maxBlk - blkCnt); + + if(blksToGet == 0) { + return err; + } + + log = malloc(blksToGet * 512); + + if (!log) { + fprintf(stderr, "could not alloc buffer for log\n"); + return EINVAL; + } + + memset(log, 0, blksToGet * 512); + + err = nvme_get_log_with_offset(fd, cfg.namespace_id, log_id, blksToGet * 512, offset, (void *)log); + if (!err) { + offset += blksToGet * 512; + + if (!cfg.raw_binary) { + printf("\nBlock # :%d to %d\n", blkCnt + 1, blkCnt + blksToGet); + + d((unsigned char *)log, blksToGet * 512, 16, 1); + } else + seaget_d_raw((unsigned char *)log, blksToGet * 512, dump_fd); + } else if (err > 0) + fprintf(stderr, "NVMe Status:%s(%x)\n", + nvme_status_to_string(err), err); + else + perror("log page"); + + blkCnt += blksToGet; + + free(log); + } + return err; + +} + +void seaget_d_raw(unsigned char *buf, int len, int fd) +{ + /********************* + int i; + fflush(stdout); + for (i = 0; i < len; i++) + putchar(*(buf+i)); + *********************/ + + 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"; + int err, fd, 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 = "", + }; + + const struct argconfig_commandline_options command_line_options[] = { + {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace_id}, + {"dump-file", 'f', "FILE", CFG_STRING, &cfg.file, required_argument, file}, + {NULL} + }; + + fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); + if (fd < 0) + return fd; + + dump_fd = STDOUT_FILENO; + + if(strlen(cfg.file)) { + dump_fd = open(cfg.file, flags, mode); + if (dump_fd < 0) { + perror(cfg.file); + return EINVAL; + } + } + + log_id = 0x08; + err = nvme_get_log_with_offset(fd, cfg.namespace_id, log_id, sizeof(tele_log), offset, (void *)(&tele_log)); + if (!err) { + + maxBlk = tele_log.tele_data_area3; + offset += 512; + + /*************************************************************************** + 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); + ***************************************************************************/ + + seaget_d_raw((unsigned char *)(&tele_log), sizeof(tele_log), dump_fd); + + } else if (err > 0) + fprintf(stderr, "NVMe Status:%s(%x)\n", + nvme_status_to_string(err), err); + else + perror("log page"); + + blkCnt = 0; + + while(blkCnt < maxBlk) + { + blksToGet = ((maxBlk - blkCnt) >= TELEMETRY_BLOCKS_TO_READ) ? TELEMETRY_BLOCKS_TO_READ : (maxBlk - blkCnt); + + if(blksToGet == 0) { + return err; + } + + log = malloc(blksToGet * 512); + + if (!log) { + fprintf(stderr, "could not alloc buffer for log\n"); + return EINVAL; + } + + memset(log, 0, blksToGet * 512); + + err = nvme_get_log_with_offset(fd, cfg.namespace_id, log_id, blksToGet * 512, offset, (void *)log); + if (!err) { + offset += blksToGet * 512; + + seaget_d_raw((unsigned char *)log, blksToGet * 512, dump_fd); + + } else if (err > 0) + fprintf(stderr, "NVMe Status:%s(%x)\n", + nvme_status_to_string(err), err); + else + perror("log page"); + + blkCnt += blksToGet; + + free(log); + } + + if(strlen(cfg.file)) { + close(dump_fd); + } + + + return err; + +} + + +//SEAGATE-PLUGIN Version +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 diff --git a/seagate-nvme.h b/seagate-nvme.h new file mode 100755 index 00000000..78c9f58b --- /dev/null +++ b/seagate-nvme.h @@ -0,0 +1,47 @@ +// +// 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. + +#undef CMD_INC_FILE +#define CMD_INC_FILE seagate-nvme + +#if !defined(SEAGATE_NVME) || defined(CMD_HEADER_MULTI_READ) +#define SEAGATE_NVME + +#include "cmd.h" + +PLUGIN(NAME("seagate", "Seagate vendor specific extensions"), + COMMAND_LIST( + ENTRY("vs-temp-stats", "Retrieve Seagate temperature statistics ", temp_stats) + ENTRY("vs-temperature-stats", "Retrieve Seagate temperature statistics ", temp_stats_wrapper) + ENTRY("vs-log-page-sup", "Retrieve Seagate Supported Log-pages Information ", log_pages_supp) + ENTRY("vs-smart-log", "Retrieve Seagate extended-SMART Information ", vs_smart_log) + ENTRY("vs-smart-add-log", "Retrieve Seagate extended-SMART Information ", vs_smart_log_wrapper) + ENTRY("vs-pcie-stats", "Retrieve Seagate PCIe error statistics ", vs_pcie_error_log) + ENTRY("clr-pcie-errs", "Clear Seagate PCIe error statistics ", vs_clr_pcie_correctable_errs) + ENTRY("clear-pcie-correctable-errors", "Clear Seagate PCIe error statistics ", vs_clr_pcie_correctable_errs_wrapper) + 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("plugin-version", "Shows Seagate plugin's version information ", seagate_plugin_version) + ) +); + +#endif +#include "define_cmd.h"