/* Copyright (c) Huawei Technologies Co., Ltd. 2025-2025. All rights reserved.
 * openUBMC is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
#ifndef SML_PD_H
#define SML_PD_H

#include "sml_base.h"
#include "sml_common.h"
#include "sml_oob.h"
#include "sml_physical_drive.h"

#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */

#pragma pack(1)
#define FILE_SUFFIX_MAX_LEN 16

#define PD_LOG_DATA_MAX_LEN 65535

#define PROP_VAL_LENGTH   64

#define SCSI_LOG_SELF_TEST_LOG_NUM 20
#define SCSI_LOG_SELF_TEST_LOG_DATA_LEN 20

#define PD_LOG_SAS_ERR_COUNT_LOG_MAX_BYTES 512
#define PD_LOG_SAS_GLIST_MAX_BYTES 2048
#define PD_LOG_SAS_IE_LOG_MAX_BYTES 512
#define PD_LOG_SAS_SELF_TEST_MAX_BYTES 404

#define PD_LOG_SATA_SMART_ATTR_MAX_SECTORS 1
#define PD_LOG_SATA_EXTENT_ERROR_LOG_MAX_SECTORS 5
#define PD_LOG_SATA_EXTENDED_SELF_TEST_MAX_SECTORS 5

#define MAX_PROPERTY_VALUE_LEN 129  /* 属性值的最大长度 */

#define SAS_SMART_ASC_COLLECT_ID 1
#define SAS_SMART_ASCQ_COLLECT_ID 2

#define SMART_ID "ID"
#define SMART_VALUE "VALUE"
#define SMART_RAW "RAW_VALUE"
#define SMART_FALG "FLAGS"
#define SMART_WORST "WORST"
#define SMART_THRESHOLD "THRESHOLD"
#define SMART_TYPE "TYPE"
#define SMART_UPDATED "UPDATED"
#define SMART_WHEN_FAILED "WHEN_FAILED"

#define ERR_CODE_ABORTED "ABRT"                // ABORTED
#define ERR_CODE_ADDR_MARK_NOT_FOUND "AMNF"    // ADDRESS MARK NOT FOUND
#define ERR_CODE_CMD_COMPLETION_TIMEOUT "CCTO" // COMMAND COMPLETION TIMED OUT
#define ERR_CODE_END_OF_MEDIA "EOM"            // END OF MEDIA
#define ERR_CODE_INTERFACE_CRC_ERROR "ICRC"    // INTERFACE CRC ERROR
#define ERR_CODE_ID_NOT_FOUND "IDNF"           // ID NOT FOUND
#define ERR_CODE_ILI "ILI"                     // MEANING OF THIS BIT IS COMMAND-SET SPECIFIC
#define ERR_CODE_MEDIA_CHANGED "MC"            // MEDIA CHANGED
#define ERR_CODE_MEDIA_CHANGE_REQUEST "MCR"    // MEDIA CHANGE REQUEST
#define ERR_CODE_NO_MEDIA "NM"                 // NO MEDIA
#define ERR_CODE_OBSOLETE "OBS"                // OBSOLETE
#define ERR_CODE_TRACK0_NOT_FOUND "TK0NF"      // TRACK 0 NOT FOUND
#define ERR_CODE_UNCORRECTABLE "UNC"           // UNCORRECTABLE
#define ERR_CODE_WRITE_PROTECTED "WP"          // WRITE PROTECTED
#define PD_LOG_COLLECT_TIMEOUT (180 * 1000) // 单个日志数据收集的超时时间180s

#define PD_LOG_BASE_PATH "/data/var/log/storage/drivelog"

#define PD_LOG_SOURCE_OOB 0
#define PD_LOG_SOURCE_BMA 1

typedef struct tag_sml_pd_log_data {
    SML_PD_LOG_TYPE_E log_type;   // 日志类型
    union {
        guint16 sectors; // SATA 盘日志数据长度按sector个数计算
        guint32 bytes;   // SAS 盘日志数据长度按byte计算
    }max_raw_data_size;
    gint32  result;
    guint32 scsi_status_code;   // 收集失败时的SCSI Status Code
    guint32 data_length; // 原始数据长度
    guint8* data;        // 动态分配的内存，存放日志的原始数据
} SML_PD_LOG_DATA_S;

typedef struct tag_sml_pd_log {
    guint8  i_controller_index;
    guint16 i_device_id;
    SML_PD_LOG_DATA_S log;
}SML_PD_LOG_S;

typedef struct _tag_pd_log {
    guint8 log_source; // 0 - OOB, 1 - BMA, 其它值无效
    guint8 log_rotate_num;
    guint8 pd_power_state;
    guint8 pd_interface_type;
    guint8 pd_media_type;
    guint8 pd_slot_number;
    guint8 pd_remnant_media_wearout;
    guint16 pd_enclosure_id;
    gchar pd_device_name[PROP_VAL_LENGTH];
    gchar pd_interface_type_str[PROP_VAL_LENGTH];
    gchar pd_manufacturer[SML_PD_MANUFACTURER_LENGTH];
    gchar pd_serial_number[SML_PD_SN_LENGTH];
    gchar pd_model[SML_PD_MODEL_LENGTH];
    guint8 pd_rebuild_progress;
    guint8 pd_health;
    guint32 pd_perfail_error_count;
    guint32 pd_media_error_count;
    guint32 pd_other_error_count;

    union {
        struct {
            SML_PD_LOG_DATA_S smart_attribute;
            SML_PD_LOG_DATA_S smart_attribute_threshold;
            SML_PD_LOG_DATA_S error;
            SML_PD_LOG_DATA_S extent_error;
            SML_PD_LOG_DATA_S extended_selftest;
            SML_PD_LOG_DATA_S phy_event;
            SML_PD_LOG_DATA_S seagate_glist;
            SML_PD_LOG_DATA_S seagate_plist;
            SML_PD_LOG_DATA_S seagate_critical_event;
            SML_PD_LOG_DATA_S seagate_farm;
            SML_PD_LOG_DATA_S seagate_factory_farm;
        } SATADevice;

        struct {
            SML_PD_LOG_DATA_S selftest;
            SML_PD_LOG_DATA_S read_error_cnt;
            SML_PD_LOG_DATA_S write_error_cnt;
            SML_PD_LOG_DATA_S verify_error_cnt;
            SML_PD_LOG_DATA_S nonmedium_error_cnt;
            SML_PD_LOG_DATA_S phy_error_cnt;
            SML_PD_LOG_DATA_S glist;
            SML_PD_LOG_DATA_S temperature;
            SML_PD_LOG_DATA_S ie;
            SML_PD_LOG_DATA_S bms;
            SML_PD_LOG_DATA_S general_statistics;
            SML_PD_LOG_DATA_S huawei_specific32h;
            SML_PD_LOG_DATA_S huawei_specific34h;
            SML_PD_LOG_DATA_S huawei_specific35h;
            SML_PD_LOG_DATA_S huawei_io_info;
            SML_PD_LOG_DATA_S kioxia_ssd_specific;
            SML_PD_LOG_DATA_S kioxia_eopt;
            SML_PD_LOG_DATA_S kioxia_smart_data;
        } SASDevice;
    };
} PD_LOG_S;

typedef struct _tag_pd_log_message {
    gchar file_path[MAX_FILEPATH_LENGTH + 1];
    gchar file_suffix[FILE_SUFFIX_MAX_LEN + 1];
} PD_LOG_MSG_S;

/***************************************************************/
/* 变量名称前缀 i - input,表示在调用对应的接口时此变量是输入参数 */
/* 变量名称前缀 o - output,表示在调用对应的接口时此变量是是输出参数 */
/**************************************************************/

// ------------PD的健康状态
typedef struct tag_sml_pd_health_status {
    guint8  i_controller_index; // RAID控制器的索引号，从0开始
    guint16 i_device_id; // PD的设备ID，唯一标识
    guint16 o_health_status_code;
    /*
    bit0: 1- media error
    bit1: 1- predictive fail
    bit2: 1- other error
    other: reserved
    */
} SML_PD_HEALTH_STATUS_S;

#define SL_MAX_MANUFACTURE_DATA_LEN 32
// ------------PD的SMART信息
typedef struct _tag_SML_PD_SAS_SMART_INFO {
    guint32 strip_temperature;
    guint32 glist_len;
    guint32 plist_len;
    gchar manufacture_data[SL_MAX_MANUFACTURE_DATA_LEN];
    guint32 blocks_sent;
    guint32 blocks_received;
    guint32 minutes_left;
} SML_PD_SAS_SMART_INFO;

//  ------------PD是否是FDE(Full Disk Encryption)
typedef struct tag_sml_pd_fde_capable {
    guint8  i_controller_index;  // RAID控制器的索引号，从0开始
    guint16 i_device_id;  // PD的设备ID，唯一标识
    guint8  o_fde_capable;
    /*
    1=FDE drive, 0=non-FDE
    */
} SML_PD_FDE_CAPABLE_S;

// ------------PD的FW状态
typedef struct tag_sml_pd_fw_status {
    guint8  i_controller_index; // RAID控制器的索引号，从0开始
    guint16 i_device_id; // PD的设备ID，唯一标识
    guint8 o_fw_state;
    /*
    0x00 :Unconfigured good drive
    0x01 :Unconfigured bad drive
    0x02 :Hot spare drive
    0x10 :Configured - good drive (data invalid)
    0x11 :Configured - bad drive (data invalid)
    0x14 :Configured - drive is rebuilding
    0x18 :Configured - drive is online
    0x20 :drive is getting copied
    0x40 :drive is exposed and controlled by host
    0x80 :UnConfigured - shielded
    0x82 :Hot Spare - shielded
    0x90 :Configured - shielded
    */
} SML_PD_FW_STATE_S;

// ------------PD的SN
typedef struct tag_sml_pd_sn {
    guint8  i_controller_index; // RAID控制器的索引号，从0开始
    guint16 i_device_id; // PD的设备ID，唯一标识
    gchar  o_pd_sn[SML_PD_SN_LENGTH];
    gchar  previous_sn[SML_PD_SN_LENGTH];
} SML_PD_SN_S;

// ------------PD的型号
typedef struct tag_sml_pd_model {
    guint8  i_controller_index; // RAID控制器的索引号，从0开始
    guint16 i_device_id; // PD的设备ID，唯一标识
    gchar   o_pd_model[SML_PD_MODEL_LENGTH];
} SML_PD_MODEL_S;

// ------------PD的FW版本
typedef struct tag_sml_fw_version {
    guint8  i_controller_index; // RAID控制器的索引号，从0开始
    guint16 i_device_id; // PD的设备ID，唯一标识
    gchar   o_pd_fw_version[SML_PD_FW_VERSION_LENGTH];
} SML_PD_FW_VERSION_S;

// ------------PD的容量大小
typedef struct tag_sml_pd_capacity {
    guint8  i_controller_index; // RAID控制器的索引号，从0开始
    guint16 i_device_id; // PD的设备ID，唯一标识
    guint32 o_capcity_size;
    guint16 o_block_size; // 硬盘块大小
} SML_PD_CAPACITY_S;

// ------------PD的媒介类型
typedef struct tag_sml_pd_media_type {
    guint8  i_controller_index; // RAID控制器的索引号，从0开始
    guint16 i_device_id; // PD的设备ID，唯一标识
    guint8  o_media_type;
} SML_PD_MEDIA_TYPE_S;

// ------------PD的接口类型
typedef struct tag_sml_pd_interface_type {
    guint8  i_controller_index; // RAID控制器的索引号，从0开始
    guint16 i_device_id; // PD的设备ID，唯一标识
    guint8  o_if_type;
    /*
    0:Unknown
    1:parallel SCSI,
    2:SAS
    3:SATA
    4:FC
    other: reserved
    */
} SML_PD_INTERFACE_TYPE_S;

// ------------PD的支持的最大速率
typedef struct tag_sml_pd_device_speed {
    guint8  i_controller_index; // RAID控制器的索引号，从0开始
    guint16 i_device_id; // PD的设备ID，唯一标识
    guint8  o_device_speed;
    /*
    0: MR_PD_SPEED_UNKNOWN
    1: MR_PD_SPEED_1p5G
    2: MR_PD_SPEED_3G
    3: MR_PD_SPEED_6G
    4: MR_PD_SPEED_12G
    other: reserved
    */
} SML_PD_DEVICE_SPEED_S;

// ------------PD的Link速率
typedef struct tag_sml_pd_link_speed {
    guint8  i_controller_index; // RAID控制器的索引号，从0开始
    guint16 i_device_id; // PD的设备ID，唯一标识
    guint8  o_link_speed;
} SML_PD_LINK_SPEED_S;

// ------------PD的厂商
typedef struct tag_sml_pd_manufacturer {
    guint8  i_controller_index; // RAID控制器的索引号，从0开始
    guint16 i_device_id; // PD的设备ID，唯一标识
    gchar   o_manufacturer[SML_PD_MANUFACTURER_LENGTH];
} SML_PD_MANUFACTURER_S;
// ------------PD的厂商ID
typedef struct tag_sml_pd_verdorid {
    guint8  i_controller_index; // RAID控制器的索引号，从0开始
    guint16 i_device_id; // PD的设备ID，唯一标识
    guint32  o_vendorid;
} SML_PD_VENDORID_S;

// ------------PD的SAS地址
typedef struct tag_sml_pd_sas_addr {
    guint8  i_controller_index; // RAID控制器的索引号，从0开始
    guint16 i_device_id; // PD的设备ID，唯一标识
    gchar   o_sas_addr1[SML_SAS_ADDR_LENGTH];
    gchar   o_sas_addr2[SML_SAS_ADDR_LENGTH];
} SML_PD_SAS_ADDR_S;

// ------------PD的热备状态
typedef struct tag_sml_pd_hot_spare_status {
    guint8  i_controller_index; // RAID控制器的索引号，从0开始
    guint16 i_device_id; // PD的设备ID，唯一标识
    guint8  o_hot_spare;
    /*
    0：no hot spare
    1：global hot spare
    2：dedicated spare
    other: reserved
    */
} SML_PD_HOT_SPARE_STATUS_S;

// ------------PD的重构状态
typedef struct tag_sml_pd_rebuild_status {
    guint8  i_controller_index; // RAID控制器的索引号，从0开始
    guint16 i_device_id; // PD的设备ID，唯一标识
    guint8  o_is_rebuild;
    guint8  o_rebuid_progress;
} SML_PD_REBUILD_STATUS_S;

// ------------PD的巡检状态
typedef struct tag_sml_pd_patrol_status {
    guint8  i_controller_index; // RAID控制器的索引号，从0开始
    guint16 i_device_id; // PD的设备ID，唯一标识
    guint8  o_is_patrol;
    guint8  o_patrol_progress;
} SML_PD_PATROL_STATUS_S;

// ------------PD的巡检状态
typedef struct tag_sml_pd_power_status {
    guint8  i_controller_index; // RAID控制器的索引号，从0开始
    guint16 i_device_id; // PD的设备ID，唯一标识
    guint8  o_power_state;
    /*
    0: device is active (spun up)
    1: device is stopped (spun down)
    0xff: device is transitioning between power states
    */
} SML_PD_POWER_STATE_S;

// ------------PD的温度
typedef struct tag_sml_pd_temperature {
    guint8  i_controller_index; // RAID控制器的索引号，从0开始
    guint16 i_device_id; // PD的设备ID，唯一标识
    guint8  o_temperature;
} SML_PD_TEMPERATURE_S;

// ------------PD的SMART预告警状态
typedef struct tag_sml_pd_smart_prefail {
    guint8  i_controller_index; // RAID控制器的索引号，从0开始
    guint16 i_device_id; // PD的设备ID，唯一标识
    guint8  o_smart_prefail;
    /*
    0 - no prefail
    1 - has prefail
    */
} SML_PD_SMART_PREFAIL_S;

// ------------PD的SSD剩余使用寿命
typedef struct tag_sml_pd_ssd_lifeleft {
    guint8  i_controller_index; // RAID控制器的索引号，从0开始
    guint16 i_device_id; // PD的设备ID，唯一标识
    guint8  o_ssd_remnant_wearout; // 剩余擦写次数的百分比
    /*
    0 - 100: percentage of life left
    255 : not support
    */
} SML_PD_SSD_REMNANT_MEDIA_WEAROUT_S;


// ------------PD的SSD累计通电时间
typedef struct tag_sml_pd_ssd_power_on_hours {
    guint8  i_controller_index; // RAID控制器的索引号，从0开始
    guint16 i_device_id; // PD的设备ID，唯一标识
    guint32  o_ssd_power_on_hours; //
} SML_PD_SSD_POWER_ON_HOURS_S;

// ------------PD的SSD预估剩余寿命
typedef struct tag_sml_pd_ssd_estimated_remaining_lifespan {
    guint8  o_interface_type;
    guint8  o_media_type;
    guint8  o_slot_num;
    guint8  i_controller_index; // RAID控制器的索引号，从0开始
    guint16 i_device_id; // PD的设备ID，唯一标识
    guint32 o_ssd_est_lifespan_value;
    gchar   o_serial_num[SML_PD_MANUFACTURER_LENGTH];
    SML_PD_ESTIMATED_LIFESPAN_INFO_S o_est_cur_info;
} SML_PD_SSD_EST_REMN_LIFESPAN_S;

// ------------PD的SSD预估剩余寿命
typedef struct tag_sml_pd_ssd_write_amp_factor {
    guint8  i_controller_index; // RAID控制器的索引号，从0开始
    guint16 i_device_id; // PD的设备ID，唯一标识
    gchar   o_serial_num[SML_PD_MANUFACTURER_LENGTH];
    guint32 o_ssd_write_amp_value;
    SML_PD_WRITE_AMP_INFO_S o_write_amp_cur_info;
} SML_PD_SSD_WRITE_AMP_FACTOR_S;

// ------------PD的错误统计
typedef struct tag_sml_pd_error_count {
    guint8  i_controller_index; // RAID控制器的索引号，从0开始
    guint16 i_device_id; // PD的设备ID，唯一标识
    guint32 o_media_err_count;
    guint32 o_other_err_count;
    guint32 o_predictive_fail_count;
} SML_PD_ERR_COUNT_S;

// PD的转速
typedef struct {
    guint8  i_controller_index; // RAID控制器的索引号，从0开始
    guint16 i_device_id;        // PD的设备ID，唯一标识
    guint16 o_rotation_speed;
} SML_PD_ROTATION_SPEED;

// PD的尺寸
typedef struct {
    guint8  i_controller_index; // RAID控制器的索引号，从0开始
    guint16 i_device_id;        // PD的设备ID，唯一标识
    guint8  o_form_factor;
} SML_PD_FORM_FACTOR;

// ------------Dump PD SMART info
typedef struct tag_sml_pd_smart_dump {
    guint8  i_controller_index; // RAID控制器的索引号，从0开始
    gchar   i_file_path[PATH_MAX];
    gchar   i_file_short_name[NAME_MAX];
} SML_PD_SMART_DUMP_S;

/* 支持采集的数据列表 */
typedef struct tag_sml_pd_smart_collect_info {
    guint8  i_controller_index;
    guint16 i_device_id;
    /* 此处无法引用到SML_PD_SMART_INFO_S的定义，定义为通用指针 */
    SML_PD_SMART_INFO_S smart_info;
}SML_PD_SMART_COLLECT_INFO_S;

// ----------------硬盘故障诊断
typedef struct tag_sml_pd_fault_analysis {
    guint8 i_controller_index;
    guint16 i_pd_device_id;
    guint16 i_encl_device_id;
    guint8 i_pd_error;  // 用于链路诊断
    union {
        struct {
#ifndef BD_BIG_ENDIAN
            guint32 sense_error : 1;
            guint32 encl_comm_error : 1;
            guint32 ctrl_encl_link_error : 1;
            guint32 encl_pd_link_error : 1;
            guint32 ctrl_pd_link_error : 1;
            // expander到expander的链路，共三个bit位，第n位bit表示离硬盘的第n级encl_ecnl链路有问题
            guint32 encl_encl_link_error : 3;
            guint32 pd_smart_log_error : 1;    // error标志,任何SMART属性(除了crc错误)或标准日志诊断出异常则标记
            guint32 pd_crc_error : 1;          // crc错误时需要结合链路诊断特殊处理
            guint32 pd_passthru_cmd_fail : 1;  // 硬盘直通命令发送失败，需要结合链路诊断特殊处理
            guint32 pd_short_dst_error : 1;    // 硬盘short dst检测失败
            guint32 reserved : 20;
#else
            guint32 reserved : 20;
            guint32 pd_short_dst_error : 1;
            guint32 pd_passthru_cmd_fail : 1;
            guint32 pd_crc_error : 1;
            guint32 pd_smart_log_error : 1;
            guint32 encl_encl_link_error : 3;
            guint32 ctrl_pd_link_error : 1;
            guint32 encl_pd_link_error : 1;
            guint32 ctrl_encl_link_error : 1;
            guint32 encl_comm_error : 1;
            guint32 sense_error : 1;
#endif
        }o_fault_bitmap;
        guint32 o_fault_dword;
    };
    // sas 接口的华为和记忆硬盘在匹配sense 故障的时候，通过此数组传递厂商信息，
    // 此数组同时用于记录维护日志的信息。
    gchar io_buf[SML_MAX_DETAIL_DESC_SIZE];
}SML_PD_FAULT_ANALYSIS;

// -----------启动盘优先级
typedef struct tag_sml_pd_bootable {
    guint8 i_controller_index; // RAID控制器的索引号，从0开始
    guint16 i_device_id;    // PD的设备ID，唯一标识
    guint8 o_bootable;
    guint8 o_boot_priority;  // 启动盘优先级
} SML_PD_BOOT_PRIORITY_S;

// ------------硬盘的慢盘检测信息
typedef struct tag_sml_pd_slow_data_info {
    guint32 cmd_timeout_times;
    guint32 unexpected_sense_times;
    guint32 reset_times;
    guint32 power_on_times;
} SML_PD_SLOW_DATA;

/*
 * Description: APP通过SML获取PD的日志数据
 * History: 2018-01-16  新生成函数
*/
gint32 sml_get_pd_log(SML_PD_LOG_S* pd);

/*
 * Description: APP向SML dump指定RAID控制器的PD SMART信息
 * History: 2016-02-26  新生成函数
*/
gint32 sml_dump_pd_smart_info(SML_PD_SMART_DUMP_S* pd);

/*
 * Description: APP通过SML对PD执行操作
 * History: 2016-02-26  新生成函数
*/
gint32 sml_pd_operation(SML_PD_OPERTATION_S* pd);

/*
 * Description: APP通过SML检查pd的sense code，判断是否需要上报故障
 * History: 2019-02-15  新生成函数
*/
gboolean sml_check_pd_sense_code(SCSI_SENSE_DISECT_S *sense_info);

/* 支持采集的数据列表 */
gint32 sml_collect_hdd_smart_data(SML_PD_SMART_COLLECT_INFO_S* pd);

/*
 * Description: 打印ATA smart 信息到buf
 * History: 2017-05-9
*/
void sml_parse_ata_smart_attr_raw_value(gchar* buf, guint32 buf_size, ATA_SMART_ATTRIBUTE_S* smart_attr,
    guint8* format);

/*
 * Description: 获取SMART Attribute的名称
 * History: 2018-01-10   新生成函数
*/
const gchar* sml_get_ata_smart_attr_name(guint8 attr_id);

/*
 * Description: 诊断Expander与RAID卡之间的通信故障
 * History: 2019-01-7  新生成函数
*/
gint32 sml_diagnose_encl_comm_error(SML_PD_FAULT_ANALYSIS* diag_info);

/*
 * Description: APP调用该接口诊断硬盘的sense error
 * History: 2019-01-10  新生成函数
*/
gint32 sml_diagnose_pd_sense_error(SML_PD_FAULT_ANALYSIS* diag_info);

/*
 * Description: APP向SML获取指定RAID控制器PD的SMART全量信息字符串
 */
gint32 sml_get_smart_data_str(guint8 controller_index, guint16 pd_device_id, guint8 hdd_intf_type,
    GVariant **smart_info_var);

#pragma pack()

#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */
#endif
