/* 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.
 */

#include "hs_ctrl.h"
#include "histore/tool_lib.h"
#include "hs_misc.h"
#include "hs_drive_upgrade.h"

#define LONGB3(a) ((guint8)(((a) >> 24) & 0xff))
#define CC_PERIOD_DAY_TO_HOUR 24
#define REQ_DATA_LEN (ADM_MAX_DATA_SIZE - sizeof(struct log_rsp_head))  // 4072
#define AP_LOG_MAX_CNT          162  // 641K
#define AP_LOG_INDEX_MAX_CNT    81  // 321K
#define DUMP_FILE_MAX_CNT       644 // 2.5M
#define FLASH_DUMP_FILE_MAX_CNT 0 // 暂不实现
#define IMU_LOG_MAX_CNT         33 // 129K
#define IMU_LOG_INDEX_MAX_CNT   33 // 128K
#define AP_LASTWORD_MAX_CNT     33 // 128K
#define NAND_LOG_FILE_MAX_CNT   747 // 2.9M

typedef enum _tag_log_info_flag_type {
    FLAG_HEAD = 0,
    FLAG_MID,
    FLAG_END
} LOG_INFO_FLAG_TYPE_E;

typedef struct _tag_log_cmd {
    guint8 log_type;
    guint8 collect_type;
    guint16 subopcode;
    guint32 max_data_count;
} LOG_CMD_S;

static guint8 g_uint8_reverse_table[] = {
    0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
    0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
    0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
    0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
    0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
    0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
    0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
    0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
    0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
    0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
    0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
    0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
    0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
    0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
    0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
    0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
};

static LOG_CMD_S g_log_cmd[] = {
    {CTRL_AP_LOG_TYPE,          AP_LOG_TYPE,        ADM_CMD_GET_LOG,      AP_LOG_MAX_CNT},
    {CTRL_IMU_LOG_TYPE,         IMU_LOG_TYPE,       ADM_CMD_GET_LOG,      IMU_LOG_MAX_CNT},
    {CTRL_AP_LOG_INDEX,         AP_LOG_INDEX,       ADM_CMD_GET_LOG,      AP_LOG_INDEX_MAX_CNT},
    {CTRL_IMU_LOG_INDEX,        IMU_LOG_INDEX,      ADM_CMD_GET_LOG,      IMU_LOG_INDEX_MAX_CNT},
    {CTRL_AP_LASTWORD_TYPE,     AP_LASTWORD_TYPE,   ADM_CMD_GET_LOG,      AP_LASTWORD_MAX_CNT},
    {CTRL_FLASH_DUMP_FILE_TYPE, DUMP_FILE_TYPE,     ADM_CMD_GET_DUMP,     FLASH_DUMP_FILE_MAX_CNT},
    {CTRL_DUMP_FILE_TYPE,       DUMP_RAM_FILE_TYPE, ADM_CMD_GET_DUMP,     DUMP_FILE_MAX_CNT},
    {CTRL_NAND_LOG0_FILE_TYPE,  NAND_FILE_TYPE,     ADM_CMD_GET_NAND_LOG, NAND_LOG_FILE_MAX_CNT},
    {CTRL_NAND_LOG1_FILE_TYPE,  NAND_FILE_TYPE,     ADM_CMD_GET_NAND_LOG, NAND_LOG_FILE_MAX_CNT},
};

static gint32 syslog(int level, char *fmt, ...)
{
    return RET_OK;
}

/*
 * Description: 初始化某个Hi1880 RAID控制器
 */
gint32 histore_init_ctrl_manage(guint32 ctrl_id, MCTP_WRITEREAD_FUNC mctp_writeread_func)
{
    struct store_lib_conf conf;
    memset_s(&conf, sizeof(conf), 0, sizeof(conf));
    conf.adapter_num = 8; // 8 默认支持
    conf.cmd_timeout_ms = HISTORE_CMD_TIMEOUT_DEFAULT; // 默认超时时间，全命令生效
    conf.event_poll_interval = 0;
    conf.func_list.mctp_send = mctp_writeread_func;
    conf.func_list.syslog = syslog;
    conf.func_list.event_hand = NULL;
    return libhistore_init(&conf);
}

/*
 * Description: 退出Hi1880 RAID带外管理
 */
gint32 histore_exit_ctrl_manage(guint32 ctrl_id, MCTP_WRITEREAD_FUNC mctp_writeread_func)
{
    return libhistore_exit();
}

/*
 * Description: 获取控制器基本信息
 */
static gint32 get_ctrl_info(guint32 ctrl_id, struct cmd_controller_info *ctrl_basic_info)
{
    struct lib_cmd_param lib_param;

    (void)memset_s(&lib_param, sizeof(lib_param), 0, sizeof(lib_param));
    lib_param.opcode = ADM_RAID_READ;
    lib_param.subopcode = ADM_CMD_GET_CTRL_INFO;
    lib_param.card_id = ctrl_id;
    lib_param.channel = PCIE_PHYSICAL_FUCTION0;
    lib_param.data_len = (guint16)sizeof(struct cmd_controller_info);
    lib_param.data = ctrl_basic_info;
    return process_histore_cmd(&lib_param);
}

/*
 * Description: 获取控制器状态信息
 */
static gint32 get_ctrl_status(guint32 ctrl_id, struct cmd_controller_status *ctrl_status)
{
    struct lib_cmd_param lib_param;
    (void)memset_s(&lib_param, sizeof(lib_param), 0, sizeof(lib_param));
    lib_param.opcode = ADM_RAID_READ;
    lib_param.subopcode = ADM_CMD_GET_CTRL_STATUS;
    lib_param.card_id = ctrl_id;
    lib_param.channel = PCIE_PHYSICAL_FUCTION0;
    lib_param.data_len = (guint16)sizeof(struct cmd_controller_status);
    lib_param.data = ctrl_status;
    return process_histore_cmd(&lib_param);
}

static void get_ctrl_basic_info(SML_CTRL_BASIC_INFO_S *ctrl, const struct cmd_controller_status *ctrl_status)
{
    ctrl->ld_present_conut = ctrl_status->vd_num;
    ctrl->ld_degraded_count = ctrl_status->vd_degrade_num;
    ctrl->ld_offline_count = ctrl_status->vd_fault_num;
    ctrl->pddisk_present_count = ctrl_status->disk_num;
    ctrl->pddisk_prefail_count = ctrl_status->disk_prefail_num;
    ctrl->pddisk_fail_count = ctrl_status->disk_fail_num;
    debug_log(DLOG_DEBUG,
        "get_ctrl_basic_info ld_present_conut = %u, ld_degraded_count = %u, ld_offline_count = %u,"
        "pd_present_count = %u, pddisk_present_count =%u, pddisk_prefail_count = %u, pddisk_fail_count = %u",
        ctrl->ld_present_conut, ctrl->ld_degraded_count, ctrl->ld_offline_count, ctrl->pd_present_count,
        ctrl->pddisk_present_count, ctrl->pddisk_prefail_count, ctrl->pddisk_fail_count);
}

static void get_ctrl_memory_info(guint32 ctrl_id, SML_CTRL_BASIC_INFO_S *ctrl,
    const struct cmd_controller_status *ctrl_status)
{
    ctrl->memory_size = ctrl_status->ddr_size;
    ctrl->memory_ce_count = ctrl_status->ddr_ce_count;
    ctrl->memory_uce_count = ctrl_status->ddr_uce_count;
    ctrl->memory_ecc_count = ctrl_status->ddr_ecc_count;
    ctrl->memory_ecc_bucket_size = ctrl_status->ddr_ecc_bucket_size;
    debug_log(DLOG_DEBUG, "get_ctrl_memory_info Controller#%d Memory CE = %d, UCE = %d, "
        "ECC Count = %d, ECC Bucket Size = %d",
        SML_CTRL_ID_VALID_BIT(ctrl_id), ctrl->memory_ce_count, ctrl->memory_uce_count,
        ctrl->memory_ecc_count, ctrl->memory_ecc_bucket_size);
    return;
}

static void parse_raid_support_level(SML_CTRL_BASIC_INFO_S *ctrl, const struct cmd_controller_info *ctrl_basic_info)
{
    // 支持的raid级别，1表示支持，0表示不支持
    ctrl->raid0_supported = (ctrl_basic_info->raid_level) & BIT(0); // bit0 raid0
    ctrl->raid1_supported = (ctrl_basic_info->raid_level) & BIT(1); // bit1 raid1
    ctrl->raid10_supported = (ctrl_basic_info->raid_level) & BIT(2); // bit2 raid10
    ctrl->raid5_supported = (ctrl_basic_info->raid_level) & BIT(3); // bit3 raid5
    ctrl->raid50_supported = (ctrl_basic_info->raid_level) & BIT(4); // bit4 raid50
    ctrl->raid6_supported = (ctrl_basic_info->raid_level) & BIT(5); // bit5 raid6
    ctrl->raid60_supported = (ctrl_basic_info->raid_level) & BIT(6); // bit6 raid60
    return;
}

static void shield_ctrl_invalid_value(SML_CTRL_BASIC_INFO_S *ctrl)
{
    // 不支持设置无效值
    ctrl->maint_pd_fail_history = STORAGE_INFO_INVALID_BYTE;
    ctrl->read_cache_percent = STORAGE_INFO_INVALID_BYTE;
    ctrl->spare_activation_mode = STORAGE_INFO_INVALID_BYTE;
    ctrl->nobattery_write_cache = STORAGE_INFO_INVALID_BYTE;
    return;
}

static guint8 parse_ctrl_mode_info(guint8 mode_info)
{
    guint8 mode;
    switch (mode_info) {
        case 0: // HBA 模式
            mode = CTRL_MODE_HBA;
            break;
        case 1: // RAID 模式
            mode = CTRL_MODE_RAID;
            break;
        default:
            mode = CTRL_MODE_UNKNOWN;
    }
    return mode;
}

static guint8 parse_pcie_link_width(guint8 ep_pcie_width)
{
    guint8 mode;
    switch (ep_pcie_width) {
        case 1: // x1 1
            mode = PCIE_LINK_WIDTH_X1;
            break;
        case 2: // x2 2
            mode = PCIE_LINK_WIDTH_X2;
            break;
        case 4: // x4 4
            mode = PCIE_LINK_WIDTH_X4;
            break;
        case 8: // x8 8
            mode = PCIE_LINK_WIDTH_X8;
            break;
        case 16:  // x16 16
            mode = PCIE_LINK_WIDTH_X16;
            break;
        default:
            mode = CTRL_MODE_UNKNOWN; // 0xff 未知
    }
    return mode;
}

/*
 * Description: 解析控制器 Sas link rate
 */
static guint8 parse_ctrl_link_rate(guint8 sas_ctl_speed)
{
    if (sas_ctl_speed == 12) { // 只支持12G
        return CTRL_DEVICE_INTERFACE_SAS_12G;
    } else {
        return CTRL_DEVICE_INTERFACE_INVALID;
    }
}

static void parse_ctrl_support_mode(guint32 ctrl_id, SML_CTRL_BASIC_INFO_S *ctrl)
{
    if (LONGB3(ctrl_id) == HISTORE_TYPE_HBA) {
        ctrl->operations.ctrl_operations.support_hba = 1;
    } else {
        ctrl->operations.ctrl_operations.support_raid = 1;
    }
    return;
}

static void fill_default_support(guint32 ctrl_id, SML_CTRL_BASIC_INFO_S *ctrl)
{
    ctrl->operations.pd_operations.support_temperature = 1;
    ctrl->operations.ctrl_operations.support_jbod_state = 1;
    ctrl->operations.ld_operations.support_write_policy = (LONGB3(ctrl_id) == HISTORE_TYPE_HBA) ? 0 : 1;
    ctrl->operations.ld_operations.support_read_policy = (LONGB3(ctrl_id) == HISTORE_TYPE_HBA) ? 0 : 1;
    ctrl->operations.ld_operations.support_disk_cache_policy = 1;
    return;
}

/*
 * Description: 查询是否使能指定控制器的CopyBack功能
 * History: 2022年4月22日   ()  新生成函数
*/
static gint32 get_ctrl_enable_copyback_cmd(guint32 ctrl_id, SML_CTRL_BASIC_INFO_S *ctrl)
{
    gint32 ret;
    struct lib_cmd_param lib_param;
    (void)memset_s(&lib_param, sizeof(lib_param), 0, sizeof(lib_param));
    lib_param.opcode = ADM_RAID_READ_FROM_CQE;
    lib_param.subopcode = ADM_CMD_SHOW_COPYBACK_SW;
    lib_param.card_id = ctrl_id;
    lib_param.channel = PCIE_PHYSICAL_FUCTION0;
    ret = process_histore_cmd(&lib_param);
    if (ret != SML_SUCCESS) {
        debug_log(DLOG_ERROR, "get_ctrl_copyback_enabled failed, ret = %d", ret);
        return ret;
    }
    ctrl->properties.copyback_enabled = (lib_param.result0 == 1) ? ENABLE : DISABLE;
    return SML_SUCCESS;
}

/*
 * Description: 查询指定控制器的S.M.A.R.T CopyBack功能的使能状态
 * History: 2022年4月22日   ()  新生成函数
*/
static gint32 get_ctrl_enable_smart_copyback_cmd(guint32 ctrl_id, SML_CTRL_BASIC_INFO_S *ctrl)
{
    gint32 ret;
    struct lib_cmd_param lib_param;
    (void)memset_s(&lib_param, sizeof(lib_param), 0, sizeof(lib_param));
    lib_param.opcode = ADM_RAID_READ_FROM_CQE;
    lib_param.subopcode = ADM_CMD_SHOW_PRECOPY_SW;
    lib_param.card_id = ctrl_id;
    lib_param.channel = PCIE_PHYSICAL_FUCTION0;
    ret = process_histore_cmd(&lib_param);
    if (ret != SML_SUCCESS) {
        debug_log(DLOG_ERROR, "get_ctrl_smart_copyback_enabled failed, ret = %d", ret);
        return ret;
    }
    ctrl->properties.smarter_copyback_enabled = (lib_param.result0 == 1) ? ENABLE : DISABLE;
    return SML_SUCCESS;
}

/*
 * Description: 查询指定控制器的一致性校验信息
 * History: 2022年5月16日   ()  新生成函数
*/
static gint32 get_ctrl_consis_check_cmd(guint32 ctrl_id, SML_CTRL_BASIC_INFO_S *ctrl)
{
    gint32 retval;
    struct lib_cmd_param lib_param;
    struct cmd_get_rd_cc prop;
    (void)memset_s(&lib_param, sizeof(lib_param), 0, sizeof(lib_param));
    (void)memset_s(&prop, sizeof(prop), 0, sizeof(prop));
    lib_param.opcode = ADM_RAID_READ;
    lib_param.subopcode = ADM_CMD_SHOW_CONSIS_CHECK;
    lib_param.card_id = ctrl_id;
    lib_param.channel = PCIE_PHYSICAL_FUCTION0;
    lib_param.data_len = (guint16)sizeof(struct cmd_get_rd_cc);
    lib_param.data = &prop;
    retval = process_histore_cmd(&lib_param);
    if (retval != SML_SUCCESS) {
        debug_log(DLOG_ERROR, "get_ctrl_consis_check_cmd failed, ret = %d", retval);
        return retval;
    }
    ctrl->consis_check_enabled = prop.sw;
    ctrl->consis_check_period = (guint16)(prop.period * CC_PERIOD_DAY_TO_HOUR);
    ctrl->consis_check_rate = prop.rate;
    ctrl->consis_check_repair = (prop.repair == 0) ? CTRL_CC_ENABLE : CTRL_CC_DISABLE;
    ctrl->consis_check_status = prop.run_status;
    ctrl->consis_check_totalvd = (guint16)prop.total_vd;
    ctrl->consis_check_completedvd = (guint16)prop.complete_vd;
    return SML_SUCCESS;
}

static gint32 get_ctrl_slow_drive_detection_mode(guint32 ctrl_id, SML_CTRL_BASIC_INFO_S *ctrl)
{
    struct cmd_show_slow_disk slow_drive_info = {0};
    struct lib_cmd_param lib_param = {0};

    lib_param.opcode = ADM_RAID_READ;
    lib_param.subopcode = ADM_CMD_SHOW_SLOWDISK_EX;
    lib_param.card_id = ctrl_id;
    lib_param.channel = PCIE_PHYSICAL_FUCTION0;
    lib_param.data_len = sizeof(struct cmd_show_slow_disk);
    lib_param.data = &slow_drive_info;
    gint32 ret = process_histore_cmd(&lib_param);
    if (ret != SML_SUCCESS) {
        debug_log(DLOG_ERROR, "get_ctrl_slow_drive_detection_mode failed, ret = %d", ret);
        return ret;
    }
    ctrl->member_drive_detection_sw = slow_drive_info.raid_sw;
    ctrl->raw_drive_detection_sw = slow_drive_info.raw_sw;
    return ret;
}

/*
 * Description:获取控制器配置信息
 * History: 2022年5月16日   ()  新生成函数
*/
static gint32 get_ctrl_config(guint32 ctrl_id, SML_CTRL_BASIC_INFO_S *ctrl)
{
    guint32 jbod_enabled = get_ctrl_jbod_enabled(ctrl_id);
    ctrl->properties.jbod_enabled = (jbod_enabled == ADM_CARD_PASSTHRU_RAWDRIVE) ? 1 : jbod_enabled;
    parse_ctrl_support_mode(ctrl_id, ctrl);
    fill_default_support(ctrl_id, ctrl);
    // 获取控制器copyback使能状态
    gint32 ret = get_ctrl_enable_copyback_cmd(ctrl_id, ctrl);
    if (ret != SML_SUCCESS) {
        debug_log(DLOG_ERROR, "%s get_ctrl_enable_copyback_cmd failed, ret = %d", __FUNCTION__, ret);
        return ret;
    }
    // 获取控制器smart_copyback使能状态
    ret = get_ctrl_enable_smart_copyback_cmd(ctrl_id, ctrl);
    if (ret != SML_SUCCESS) {
        debug_log(DLOG_ERROR, "%s get_ctrl_enable_smart_copyback_cmd failed, ret = %d", __FUNCTION__, ret);
        return ret;
    }
    // 获取控制器consis_check使能状态
    ret = get_ctrl_consis_check_cmd(ctrl_id, ctrl);
    if (ret != SML_SUCCESS) {
        debug_log(DLOG_ERROR, "%s get_ctrl_consis_check_cmd failed, ret = %d", __FUNCTION__, ret);
        return ret;
    }
    ret = get_ctrl_slow_drive_detection_mode(ctrl_id, ctrl);
    if (ret != SML_SUCCESS) {
        debug_log(DLOG_ERROR, "%s get raid drive detection info failed, ret = %d", __FUNCTION__, ret);
        return ret;
    }
    return SML_SUCCESS;
}

/*
 * Description: 获取控制器信息
 */
gint32 histore_get_ctrl_info(guint32 ctrl_id, gpointer data)
{
    struct cmd_controller_info ctrl_basic_info;
    struct cmd_controller_status ctrl_status;

    if (data == NULL) {
        return SML_ERR_NULL_DATA;
    }
    SML_CTRL_BASIC_INFO_S *ctrl = (SML_CTRL_BASIC_INFO_S *)data;

    (void)memset_s(&ctrl_basic_info, sizeof(ctrl_basic_info), 0, sizeof(ctrl_basic_info));
    (void)memset_s(&ctrl_status, sizeof(ctrl_status), 0, sizeof(ctrl_status));
    gint32 ret = get_ctrl_info(ctrl_id, &ctrl_basic_info);
    if (ret != SML_SUCCESS) {
        debug_log(DLOG_ERROR, "%s get_ctrl_info failed, ret = %d", __FUNCTION__, ret);
        return ret;
    }
    ret = get_ctrl_status(ctrl_id, &ctrl_status);
    if (ret != SML_SUCCESS) {
        debug_log(DLOG_ERROR, "%s get_ctrl_status failed, ret = %d", __FUNCTION__, ret);
        return ret;
    }
    // LD和PD的总体统计情况
    get_ctrl_basic_info(ctrl, &ctrl_status);
    // RAID控制器内存信息
    get_ctrl_memory_info(ctrl_id, ctrl, &ctrl_status);
    ctrl->device_interface = parse_ctrl_link_rate(ctrl_basic_info.sas_ctl_speed); // 控制器的sas速率
    ctrl->cache_pinned = ctrl_status.cache_pinned; // 默认填写0
    ctrl->ctrl_temp = (guint16)ctrl_status.chip_tempature;
    debug_log(DLOG_DEBUG, "%s ctrl temp value is %d, ctrl_id = %d, raw_chip_temp = %d", __FUNCTION__,
        ctrl->ctrl_temp, ctrl_id, ctrl_status.chip_tempature);
    if (ctrl_status.current_fw == 0) { // 运行分区，0 分区
        strncpy_s(ctrl->fw_version, sizeof(ctrl->fw_version), ctrl_status.fw_version0, strlen(ctrl_status.fw_version0));
    } else { // 1 分区
        strncpy_s(ctrl->fw_version, sizeof(ctrl->fw_version), ctrl_status.fw_version1, strlen(ctrl_status.fw_version1));
    }
    strncpy_s(ctrl->ctrl_name, sizeof(ctrl->ctrl_name),
              ctrl_status.board_name, strlen(ctrl_status.board_name)); // 单板型号名称
    strncpy_s(ctrl->hardware_revision, sizeof(ctrl->hardware_revision),
              ctrl_status.chip_version, strlen(ctrl_status.chip_version));

    // 获取控制器sn
    errno_t safe_fun_ret = strncpy_s(ctrl->ctrl_sn, sizeof(ctrl->ctrl_sn), ctrl_status.board_sn,
        strlen(ctrl_status.board_sn));
    if (safe_fun_ret != EOK) {
        debug_log(DLOG_ERROR, "%s: strncpy_s fail, ret = %d", __FUNCTION__, safe_fun_ret);
    }

    // 获取pcie位宽
    ctrl->pcie_link_width = parse_pcie_link_width(ctrl_status.ep_pcie_width);
    ctrl->max_lds_per_array = ctrl_basic_info.vdnum_per_rg;
    ctrl->max_lds = ctrl_basic_info.max_vdnum;
    ctrl->min_strip = log(ctrl_basic_info.min_su_size) / log(2) + 1; // 以2为底进行转换 单位为k
    ctrl->max_strip = log(ctrl_basic_info.max_su_size) / log(2) + 1; // 以2为底进行转换 单位为k
    parse_raid_support_level(ctrl, &ctrl_basic_info);
    shield_ctrl_invalid_value(ctrl);
    // 获取控制器模式
    ctrl->mode = parse_ctrl_mode_info(ctrl_basic_info.ctrl_mod);
    return get_ctrl_config(ctrl_id, ctrl);
}

/*
 * Description: 获取控制器sas地址
 */
gint32 histore_get_ctrl_sas_addr(guint32 ctrl_id, gpointer data)
{
    if (data == NULL) {
        return SML_ERR_NULL_DATA;
    }

    struct cmd_controller_status ctrl_status;
    SML_SAS_ADDR_S *ctrl_sas_addr = (SML_SAS_ADDR_S *)data;
    (void)memset_s(&ctrl_status, sizeof(ctrl_status), 0, sizeof(ctrl_status));

    gint32 ret = get_ctrl_status(ctrl_id, &ctrl_status);
    if (ret != SML_SUCCESS) {
        debug_log(DLOG_ERROR, "%s get_ctrl_status failed, ret = %d", __FUNCTION__, ret);
        return ret;
    }
    ret = snprintf_s(ctrl_sas_addr->addr, sizeof(ctrl_sas_addr->addr), sizeof(ctrl_sas_addr->addr) - 1, "%llx",
                     ctrl_status.sas_address);
    if (ret <= 0) {
        debug_log(DLOG_ERROR, "%s: snprintf_s fail, ret = %d", __FUNCTION__, ret);
        return ret;
    }
    return SML_SUCCESS;
}

/*
 * Description: 发送命令给histore lib获取误码计数
 * History: 2021-08-14  新生成函数
 */
static gint32 get_ctrl_phy_err_count(guint32 ctrl_id, struct cmd_show_exp_phy_status *phy_status)
{
    struct lib_cmd_param lib_param;
    struct cmd_expander_id expander_id;
    (void)memset_s(&lib_param, sizeof(lib_param), 0, sizeof(lib_param));
    (void)memset_s(&expander_id, sizeof(expander_id), 0, sizeof(expander_id));
    expander_id.exp_id = 0;
    lib_param.opcode = ADM_RAID_READ;
    lib_param.subopcode = ADM_CMD_SHOW_EXP_PHY_STATUS;
    lib_param.card_id = ctrl_id;
    lib_param.channel = PCIE_PHYSICAL_FUCTION0;
    lib_param.data_len = (guint16)sizeof(struct cmd_show_exp_phy_status);
    lib_param.data = phy_status;
    lib_param.param_len = (guint16)sizeof(struct cmd_expander_id);
    errno_t securec_rv = memcpy_s(lib_param.cmd_param, sizeof(lib_param.cmd_param), &expander_id, sizeof(expander_id));
    if (securec_rv != EOK) {
        debug_log(DLOG_ERROR, "%s: memcpy_s failed, ret = %d", __FUNCTION__, securec_rv);
    }
    return process_histore_cmd(&lib_param);
}

gint32 histore_get_ctrl_phy_err_count(guint32 ctrl_id, gpointer data)
{
    guint32 idx;
    gint32 ret;
    struct cmd_show_exp_phy_status phy_status = {0};
    SML_SASPHY_INFO_S *ctrl = NULL;
    if (data == NULL) {
        return SML_ERR_NULL_DATA;
    }
    ctrl = (SML_SASPHY_INFO_S *)data;
    ret = get_ctrl_phy_err_count(ctrl_id, &phy_status);
    if (ret != SML_SUCCESS) {
        debug_log(DLOG_DEBUG, "histore_get_ctrl_phy_err_count failed, CtrlId = %d, return 0x%0x",
                  SML_CTRL_ID_VALID_BIT(ctrl_id), ret);
        return ret;
    }
    ctrl->phy_count = phy_status.phy_num;
    if (ctrl->phy_count > SML_MAX_SAS_PHY_PER_CTRL) {
        debug_log(DLOG_ERROR, "phy count out of bounds, ctrl->phy_count = %d", ctrl->phy_count);
        return SML_ERR_DATA_INVALID;
    }
    for (idx = 0; idx < ctrl->phy_count; idx++) {
        ctrl->phy_err[idx].invalid_dword_count = phy_status.phys[idx].invalid_dword_cont;
        ctrl->phy_err[idx].loss_dword_sync_count = phy_status.phys[idx].loss_of_dword_syn_cont;
        ctrl->phy_err[idx].phy_reset_problem_count = phy_status.phys[idx].phy_reset_pro_cont;
        ctrl->phy_err[idx].running_disparity_error_count = phy_status.phys[idx].run_disparity_err_cont;
        debug_log(DLOG_DEBUG, "%s invalid_dword_count: %d, loss_dword_sync_count: %d,"
                  "phy_reset_problem_count: %d running_disparity_error_count :%d",
                  __FUNCTION__, ctrl->phy_err[idx].invalid_dword_count, ctrl->phy_err[idx].loss_dword_sync_count,
                  ctrl->phy_err[idx].phy_reset_problem_count, ctrl->phy_err[idx].running_disparity_error_count);
    }
    return SML_SUCCESS;
}

static gint32 set_ctrl_enable_jbod_cmd(guint32 ctrl_id, guint8 passthru_type)
{
    struct lib_cmd_param lib_param;
    struct cmd_passthru_type jbod_enabled;
    (void)memset_s(&lib_param, sizeof(lib_param), 0, sizeof(lib_param));
    (void)memset_s(&jbod_enabled, sizeof(jbod_enabled), 0, sizeof(jbod_enabled));
    jbod_enabled.passthru_type = passthru_type;
    lib_param.opcode = ADM_RAID_SET;
    lib_param.subopcode = ADM_CMD_SET_PASSTHRU_TYPE;
    lib_param.card_id = ctrl_id;
    lib_param.channel = PCIE_PHYSICAL_FUCTION0;
    lib_param.param_len = (guint16)sizeof(struct cmd_passthru_type);
    errno_t securec_rv = memcpy_s(lib_param.cmd_param, sizeof(lib_param.cmd_param), &jbod_enabled,
                                  sizeof(jbod_enabled));
    if (securec_rv != EOK) {
        debug_log(DLOG_ERROR, "%s: memcpy_s failed, ret = %d", __FUNCTION__, securec_rv);
    }
    return process_histore_cmd(&lib_param);
}

static gint32 set_ctrl_enable_jbod(guint32 ctrl_id, guint8 enable)
{
    guint8 passthru_type;
    if (enable == 0) {
        passthru_type = ADM_CARD_PASSTHRU_OFF;
    } else {
        passthru_type = ADM_CARD_PASSTHRU_RAWDRIVE; // RAWDISK模式
    }

    /* 待设置的值与实际值一致直接返回 */
    if (get_ctrl_jbod_enabled(ctrl_id) == passthru_type) {
        return SML_SUCCESS;
    }

    gint32 ret = set_ctrl_enable_jbod_cmd(ctrl_id, passthru_type);
    if (ret != SML_SUCCESS) {
        debug_log(DLOG_ERROR, "set_ctrl_enable_jbod_cmd failed, ret = %d", ret);
        return ret;
    }
    return SML_SUCCESS;
}

/*
 * Description: 向底层传递信息设置是否使能指定控制器的CopyBack功能
 * History: 2022年4月22日   ()  新生成函数
*/
static gint32 set_ctrl_enable_copyback_cmd(guint32 ctrl_id, guint8 copyback_status)
{
    struct lib_cmd_param lib_param;
    struct cmd_copyback_status copyback_enabled;
    (void)memset_s(&lib_param, sizeof(lib_param), 0, sizeof(lib_param));
    (void)memset_s(&copyback_enabled, sizeof(copyback_enabled), 0, sizeof(copyback_enabled));
    copyback_enabled.copyback_status = copyback_status;
    lib_param.opcode = ADM_RAID_SET;
    lib_param.subopcode = ADM_CMD_SET_COPYBACK_SW;
    lib_param.card_id = ctrl_id;
    lib_param.channel = PCIE_PHYSICAL_FUCTION0;
    lib_param.param_len = (guint16)sizeof(struct cmd_copyback_status);
    errno_t securec_rv = memcpy_s(lib_param.cmd_param, sizeof(lib_param.cmd_param), &copyback_enabled,
                                  sizeof(copyback_enabled));
    if (securec_rv != EOK) {
        debug_log(DLOG_ERROR, "%s: memcpy_s failed, ret = %d", __FUNCTION__, securec_rv);
    }
    return process_histore_cmd(&lib_param);
}

/*
 * Description: 向底层传递信息设置是否使能指定控制器的S.M.A.R.T CopyBack功能
 * History: 2022年4月22日   ()  新生成函数
*/

static gint32 set_ctrl_enable_smart_copyback_cmd(guint32 ctrl_id, guint8 precopy_status)
{
    struct lib_cmd_param lib_param;
    struct cmd_precopy_status smart_copyback_enabled;
    (void)memset_s(&lib_param, sizeof(lib_param), 0, sizeof(lib_param));
    (void)memset_s(&smart_copyback_enabled, sizeof(smart_copyback_enabled), 0, sizeof(smart_copyback_enabled));
    smart_copyback_enabled.precopy_status = precopy_status;
    lib_param.opcode = ADM_RAID_SET;
    lib_param.subopcode = ADM_CMD_SET_PRECOPY_SW;
    lib_param.card_id = ctrl_id;
    lib_param.channel = PCIE_PHYSICAL_FUCTION0;
    lib_param.param_len = (guint16)sizeof(struct cmd_precopy_status);
    errno_t securec_rv = memcpy_s(lib_param.cmd_param, sizeof(lib_param.cmd_param), &smart_copyback_enabled,
        sizeof(smart_copyback_enabled));
    if (securec_rv != EOK) {
        debug_log(DLOG_ERROR, "%s: memcpy_s failed, ret = %d", __FUNCTION__, securec_rv);
    }
    return process_histore_cmd(&lib_param);
}

/*
 * Description: 设置是否使能指定控制器的S.M.A.R.T CopyBack功能
 * History: 2022年4月22日   ()  新生成函数
*/

static gint32 set_ctrl_enable_smart_copyback(guint32 ctrl_id, gpointer param)
{
    gint32 retval;
    SML_CTRL_BASIC_INFO_S prop;
    guint8 enable = *(guint8 *)param;

    retval = histore_get_ctrl_info(ctrl_id, &prop);
    if (retval != SML_SUCCESS) {
        debug_log(DLOG_ERROR,
            "smlib HISTORE: set_ctrl_enable_smart_copyback -> get_ctrl_enable_copyback_cmd failed, "
            "CtrlId = %d, return 0x%0x", SML_CTRL_ID_VALID_BIT(ctrl_id), retval);
        return retval;
    }

    // 只有属性改变了才需要执行实际的写属性操作
    if (prop.properties.smarter_copyback_enabled == enable) {
        debug_log(DLOG_ERROR,
            "smlib HISTORE: set_ctrl_enable_smart_copyback"
            " -> Setting is same as before, No need to change property");
        return SML_SUCCESS;
    }
    retval = set_ctrl_enable_smart_copyback_cmd(ctrl_id, enable);
    if (retval != SML_SUCCESS) {
        debug_log(DLOG_ERROR,
            "smlib HISTORE: set_ctrl_enable_smart_copyback"
            " -> Set ctrl properties failed, CtrlId = %d, return 0x%0x",
            SML_CTRL_ID_VALID_BIT(ctrl_id), retval);
    }
    return retval;
}


/*
 * Description: 设置是否使能指定控制器的CopyBack功能
 * History: 2022年4月22日   ()  新生成函数
*/
static gint32 set_ctrl_enable_copyback(guint32 ctrl_id, gpointer param)
{
    gint32 retval;
    SML_CTRL_BASIC_INFO_S prop;
    guint8 copyback_status = (*(guint8 *)param == 1) ? 0 : 1;

    // 获取所有属性值，不修改的属性直接按原先的值写回
    retval = get_ctrl_enable_copyback_cmd(ctrl_id, &prop);
    if (retval != SML_SUCCESS) {
        debug_log(DLOG_ERROR,
            "smlib HISTORE: set_ctrl_enable_copyback -> Get copyback properties failed, "
            "CtrlId = %d, return 0x%0x", SML_CTRL_ID_VALID_BIT(ctrl_id), retval);
        return retval;
    }

    // 只有属性改变了才需要执行实际的写属性操作
    if (prop.properties.copyback_enabled == copyback_status) {
        debug_log(DLOG_ERROR,
            "smlib HISTORE: set_ctrl_enable_copyback -> Setting is same as before, No need to change");
        return SML_SUCCESS;
    }
    retval = set_ctrl_enable_copyback_cmd(ctrl_id, copyback_status);
    if (retval != SML_SUCCESS) {
        debug_log(DLOG_ERROR,
            "smlib HISTORE: set_ctrl_enable_copyback -> Set ctrl properties failed, "
            "CtrlId = %d, return 0x%0x", SML_CTRL_ID_VALID_BIT(ctrl_id), retval);
        return retval;
    }

    return retval;
}

/*
 * Description: 设置指定控制器的一致性校验功能
 * History: 2022年5月16日   ()  新生成函数
*/
static gint32 set_ctrl_consis_check_cmd(guint32 ctrl_id, SML_CTRL_SET_CONSIS_CHECK_PARAM *param)
{
    struct lib_cmd_param lib_param;
    struct cmd_set_cc set_param;
    (void)memset_s(&set_param, sizeof(set_param), 0, sizeof(set_param));
    set_param.sw = param->sw;
    set_param.rate = param->rate;
    set_param.period = (guint8)(param->period / CC_PERIOD_DAY_TO_HOUR);
    set_param.repair = (param->repair == 0) ? CTRL_CC_ENABLE : CTRL_CC_DISABLE; /* 传入是0/1表示关/开，入参需要变为1/0 */
    set_param.delay = param->delay;
    set_param.mask = param->mask;
    (void)memset_s(&lib_param, sizeof(lib_param), 0, sizeof(lib_param));
    lib_param.opcode = ADM_RAID_SET;
    lib_param.subopcode = ADM_CMD_SET_CONSIS_CHECK;
    lib_param.card_id = ctrl_id;
    lib_param.channel = PCIE_PHYSICAL_FUCTION0;
    lib_param.param_len = (guint16)sizeof(struct cmd_set_cc);
    errno_t securec_rv = memcpy_s(lib_param.cmd_param, sizeof(lib_param.cmd_param), &set_param, sizeof(set_param));
    if (securec_rv != EOK) {
        debug_log(DLOG_ERROR, "%s: memcpy_s failed, ret = %d", __FUNCTION__, securec_rv);
    }
    return process_histore_cmd(&lib_param);
}

static gint32 set_ctrl_slow_disk_detection_mode(guint32 ctrl_id, SML_CTRL_SET_SLOW_DISK_DETECTTECTION_MODE *param)
{
    gint32 retval;
    struct lib_cmd_param lib_param = {0};
    struct cmd_set_slow_disk param_raid = {0};
    SML_CTRL_BASIC_INFO_S ctrl;

    lib_param.opcode = ADM_RAID_SET;
    lib_param.subopcode = ADM_CMD_SET_SLOWDISK_EX;
    lib_param.card_id = ctrl_id;
    lib_param.channel = PCIE_PHYSICAL_FUCTION0;
    lib_param.param_len = (guint16)sizeof(struct cmd_set_slow_disk);
    
    param_raid.type = param->type;
    param_raid.sw = param->sw;
    retval = get_ctrl_slow_drive_detection_mode(ctrl_id, &ctrl);
    if (retval != SML_SUCCESS) {
        debug_log(DLOG_ERROR, "%s get raid drive detection info failed, ret = %d", __FUNCTION__, retval);
        return retval;
    }

    if ((param_raid.type == SET_SLOW_DISK_TYPE_RAID && ctrl.member_drive_detection_sw == param_raid.sw) ||
        (param_raid.type == SET_SLOW_DISK_TYPE_RAWDRIVE && ctrl.raw_drive_detection_sw == param_raid.sw)) {
        return SML_SUCCESS;
    }
    if (memcpy_s(lib_param.cmd_param, sizeof(lib_param.cmd_param), &param_raid, sizeof(param_raid)) != EOK) {
        debug_log(DLOG_ERROR, "%s: memcpy_s failed!", __FUNCTION__);
        return SML_ERR_SEC_FUNC_FAILED;
    }
    return process_histore_cmd(&lib_param);
}

/*
 * Description: 关闭/打开/设置指定控制器的一致性校验功能总入口
 * History: 2022年5月16日   ()  新生成函数
*/

static gint32 set_ctrl_enable_consis_check(guint32 ctrl_id, SML_CTRL_SET_CONSIS_CHECK_PARAM *param)
{
    gint32 retval = SML_SUCCESS;
    gchar operation[CTRL_CC_STR_LEN] = {0};
    SML_CTRL_BASIC_INFO_S ctrl;
    (void)memset_s(&ctrl, sizeof(SML_CTRL_BASIC_INFO_S), 0, sizeof(SML_CTRL_BASIC_INFO_S));
    switch (param->sw) {
        case CTRL_CC_DISABLE:
            (void)strcpy_s(operation, CTRL_CC_STR_LEN, "Stop");
            break;
        case CTRL_CC_ENABLE:
            (void)strcpy_s(operation, CTRL_CC_STR_LEN, "Start");
            break;
        case CTRL_CC_SET:
            (void)strcpy_s(operation, CTRL_CC_STR_LEN, "Set");
            break;
        default:
            debug_log(DLOG_ERROR,
                "smlib HISTORE: set_ctrl_enable_consis_check -> Unknown operation, CrtlId = %d, return 0x%0x",
                SML_CTRL_ID_VALID_BIT(ctrl_id), retval);
            return SML_ERR_INVALID_PARAMETER;
    }
    retval = get_ctrl_consis_check_cmd(ctrl_id, &ctrl);
    if (retval != SML_SUCCESS) {
        debug_log(DLOG_ERROR,
            "smlib HISTORE: set_ctrl_enable_consis_check -> get_ctrl_consis_check_cmd failed, "
            "CtrlId = %d, return 0x%0x", SML_CTRL_ID_VALID_BIT(ctrl_id), retval);
        return retval;
    }

    // 如果重复打开/关闭功能，直接返回OK
    if (ctrl.consis_check_enabled == param->sw) {
        debug_log(DLOG_ERROR,
            "smlib HISTORE: set_ctrl_enable_consis_check"
            " -> Enabled is same as before, No need to change property");
        return SML_SUCCESS;
    }

    retval = set_ctrl_consis_check_cmd(ctrl_id, param);
    if (retval != SML_SUCCESS) {
        debug_log(DLOG_ERROR,
            "smlib HISTORE: set_ctrl_enable_consis_check -> %s consistency check failed, CtrlId = %d, return 0x%0x",
            operation, SML_CTRL_ID_VALID_BIT(ctrl_id), retval);
    }
    return retval;
}

static gint32 set_ctrl_property_operations(guint32 ctrl_id, guint8 operation, gpointer param, guint32 param_length)
{
    gint32 retval;
    guint8 enable;
    switch (operation) {
        case CTRL_OPERATION_ENABLE_JBOD:
            enable = *(guint8 *)param;
            retval = set_ctrl_enable_jbod(ctrl_id, enable);
            break;
        default:
            retval = SML_ERR_CTRL_OPERATION_NOT_SUPPORT;
            break;
    }
    return retval;
}

/*
 * Description: 向控制器发送设置属性值的命令
*/
static gint32 set_ctrl_factory_defaults_cmd(guint32 ctrl_id)
{
    struct lib_cmd_param lib_param;
    (void)memset_s(&lib_param, sizeof(lib_param), 0, sizeof(lib_param));
    lib_param.opcode = ADM_RAID_SET;
    lib_param.subopcode = ADM_CMD_RESET_DEFAULT_CFG;
    lib_param.card_id = ctrl_id;
    lib_param.channel = PCIE_PHYSICAL_FUCTION0;
    lib_param.param_len = 0;
    return process_histore_cmd(&lib_param);
}

/*
 * Description: 恢复指定控制器的默认设置
*/
static gint32 set_ctrl_restore_default(guint32 ctrl_id)
{
    gint32 ret;
    ret = set_ctrl_factory_defaults_cmd(ctrl_id);
    if (ret != SML_SUCCESS) {
        debug_log(DLOG_ERROR, "set_ctrl_factory_defaults_cmd failed, ret = %d", ret);
        return ret;
    }
    debug_log(DLOG_DEBUG, "set_ctrl_restore_default success");
    return SML_SUCCESS;
}

/*
 * Description: 查看外部配置（foreign磁盘包含的RAID配置信息）
 */
static gint32 ctrl_scan_foreign_config(guint32 ctrl_id, struct cmd_show_fncfglist *fncfg_list)
{
    struct lib_cmd_param lib_param;
    struct cmd_fncfglist_idx fncfglist_idx;
    (void)memset_s(&lib_param, sizeof(lib_param), 0, sizeof(lib_param));
    (void)memset_s(&fncfglist_idx, sizeof(fncfglist_idx), 0, sizeof(fncfglist_idx));

    fncfglist_idx.start_idx = 0; // 起始检索位置从0开始
    fncfglist_idx.count = (guint16)CMD_FNCFGLIST_ONCE_NUM; // 检索的最大数量
    lib_param.opcode = ADM_RAID_READ;
    lib_param.subopcode = ADM_CMD_SHOW_FNCFGLIST;
    lib_param.card_id = ctrl_id;
    lib_param.channel = PCIE_PHYSICAL_FUCTION0;
    lib_param.data = fncfg_list;
    lib_param.data_len = (guint16)sizeof(struct cmd_show_fncfglist);
    lib_param.param_len = (guint16)sizeof(struct cmd_fncfglist_idx);
    errno_t securec_rv = memcpy_s(lib_param.cmd_param, sizeof(lib_param.cmd_param), &fncfglist_idx,
                                  sizeof(fncfglist_idx));
    if (securec_rv != EOK) {
        debug_log(DLOG_ERROR, "%s: memcpy_s failed, ret = %d", __FUNCTION__, securec_rv);
    }

    return process_histore_cmd(&lib_param);
}

/*
 * Description: 导入外部配置（foreign磁盘包含的RAID配置信息）
 */
static gint32 ctrl_import_foreign_config(guint32 ctrl_id)
{
    struct lib_cmd_param lib_param;
    struct cmd_fncfg_param fncfg_param;
    struct cmd_show_fncfglist fncfg_list;
    struct cmd_controller_info ctrl_basic_info;

    (void)memset_s(&ctrl_basic_info, sizeof(ctrl_basic_info), 0, sizeof(ctrl_basic_info));
    gint32 retval = get_ctrl_info(ctrl_id, &ctrl_basic_info);
    if (retval != SML_SUCCESS) {
        debug_log(DLOG_ERROR, "%s get_ctrl_info failed, ret = %d", __FUNCTION__, retval);
        return retval;
    }
    if ((ctrl_basic_info.foreign_import & BIT(0)) == 0) { // 外部配置导入，BIT(0) : 1表示支持，0表示不支持
        debug_log(DLOG_DEBUG, "[%s] RAID Controller don't support importing foreign config.", __FUNCTION__);
        return SML_ERR_CTRL_OPERATION_NOT_SUPPORT;
    }
    (void)memset_s(&fncfg_list, sizeof(fncfg_list), 0, sizeof(fncfg_list));
    retval = ctrl_scan_foreign_config(ctrl_id, &fncfg_list);
    if (retval != SML_SUCCESS) {
        return retval;
    }
    if (fncfg_list.num == 0) { // 返回的外部配置的数量
        debug_log(DLOG_ERROR, "[%s] NO FOREIGN CONFIGS FOUND", __FUNCTION__);
        return SML_ERR_CONFIG_NO_FOREIGN_CONFIG;
    }

    (void)memset_s(&lib_param, sizeof(lib_param), 0, sizeof(lib_param));
    (void)memset_s(&fncfg_param, sizeof(fncfg_param), 0, sizeof(fncfg_param));
    fncfg_param.rg_guid = STORAGE_INFO_INVALID_QWORD; // 索引 all (全F)
    lib_param.opcode = ADM_RAID_SET;
    lib_param.subopcode = ADM_CMD_IMPORT_FNCFG;
    lib_param.card_id = ctrl_id;
    lib_param.channel = PCIE_PHYSICAL_FUCTION0;
    lib_param.param_len = (guint16)sizeof(struct cmd_fncfg_param);
    errno_t securec_rv = memcpy_s(lib_param.cmd_param, sizeof(lib_param.cmd_param), &fncfg_param, sizeof(fncfg_param));
    if (securec_rv != EOK) {
        debug_log(DLOG_ERROR, "%s: memcpy_s failed, ret = %d", __FUNCTION__, securec_rv);
    }

    return process_histore_cmd(&lib_param);
}

/*
 * Description: 清除外部配置（foreign磁盘包含的RAID配置信息）
 */
static gint32 ctrl_clear_foreign_config(guint32 ctrl_id)
{
    struct lib_cmd_param lib_param;
    struct cmd_fncfg_param fncfg_param;

    (void)memset_s(&lib_param, sizeof(lib_param), 0, sizeof(lib_param));
    (void)memset_s(&fncfg_param, sizeof(fncfg_param), 0, sizeof(fncfg_param));
    fncfg_param.rg_guid = STORAGE_INFO_INVALID_QWORD; // 索引 all (全F)
    lib_param.opcode = ADM_RAID_SET;
    lib_param.subopcode = ADM_CMD_CLEAR_FNCFG;
    lib_param.card_id = ctrl_id;
    lib_param.channel = PCIE_PHYSICAL_FUCTION0;
    lib_param.param_len = (guint16)sizeof(struct cmd_fncfg_param);
    errno_t securec_rv = memcpy_s(lib_param.cmd_param, sizeof(lib_param.cmd_param), &fncfg_param, sizeof(fncfg_param));
    if (securec_rv != EOK) {
        debug_log(DLOG_ERROR, "%s: memcpy_s failed, ret = %d", __FUNCTION__, securec_rv);
    }

    return process_histore_cmd(&lib_param);
}

/*
 * Description: 翻转uint32的bit位
 */
static guint32 reverse_uint32(register unsigned int x)
{
    register unsigned int tmp_x = x;
    tmp_x = (((tmp_x & 0xaaaaaaaa) >> 1) | ((tmp_x & 0x55555555) << 1));  // 前1个bit和后1个bit互换
    tmp_x = (((tmp_x & 0xcccccccc) >> 2) | ((tmp_x & 0x33333333) << 2));  // 前2个bit和后2个bit互换
    tmp_x = (((tmp_x & 0xf0f0f0f0) >> 4) | ((tmp_x & 0x0f0f0f0f) << 4));  // 前4个bit和后4个bit互换
    tmp_x = (((tmp_x & 0xff00ff00) >> 8) | ((tmp_x & 0x00ff00ff) << 8));  // 前8个bit和后8个bit互换
    return (guint32)((tmp_x >> 16) | (tmp_x << 16));  // 前16个bit和后16个bit互换
}

/*
 * Description: 计算1880日志数据的crc32
 * Note: 1880计算crc32时采用0x04C11DB7、左移、初值为0、结果不按位取反。
 *       PME提供的arith_make_crc32采用0xEDB88320、右移、初值为0xFFFFFFFF、结果按位取反
 *       为了使用arith_make_crc32（0xEDB88320和右移无法改变）计算得到一样的结果，需要
 *       1、将data按位翻转、结果按位翻转
 *       2、初值设置为0xFFFFFFFF、结果按位取反
 * References: https://github.com/Michaelangel007/crc32
 */
static guint32 calc_hs_log_crc32(guint8 *data, guint32 data_len)
{
    if (data_len == 0) {
        return STORAGE_INFO_INVALID_DWORD;
    }

    guint8 *tmp = g_malloc0(data_len);
    if (tmp == NULL) {
        debug_log(DLOG_ERROR, "%s: g_malloc0 failed.", __FUNCTION__);
        return STORAGE_INFO_INVALID_DWORD;
    }

    for (guint32 i = 0; i < data_len; i++) {
        tmp[i] = g_uint8_reverse_table[data[i]]; // 通过查表法翻转uint8的bit位
    }

    guint32 crc32 = arith_make_crc32((guint32)-1, tmp, data_len);
    g_free(tmp);
    return reverse_uint32(~crc32);
}

/*
 * Description: 保存数据
 */
static gint32 save_ret_data(struct lib_cmd_param *lib_param, SML_CTRL_LOG_DATA_S *ctrl_log)
{
    struct log_rsp_head *rsp = lib_param->data;
    guint8 *data = (guint8 *)rsp + sizeof(struct log_rsp_head);  // 移动指针到数据部分
    guint32 data_len = rsp->rsp_len;
    // 数据crc校验
    guint32 crc32 = calc_hs_log_crc32(data, data_len);
    if (crc32 != rsp->data_slice_crc) {
        debug_log(DLOG_ERROR, "%s: crc32 check failed!", __FUNCTION__);
        return SML_ERR_DATA_INVALID;
    }
    // 保存数据到内存
    gsize len = ctrl_log->log_length + data_len;
    guint8 *buf = g_malloc0(len);
    if (buf == NULL) {
        debug_log(DLOG_ERROR, "%s: g_malloc0 failed, len = %"G_GSIZE_FORMAT"", __FUNCTION__, len);
        return SML_ERR_CANNOT_ALLOC_MEM;
    }

    // 原数据拷贝到新地址
    errno_t securec_rv;
    if (ctrl_log->log_buffer) {
        securec_rv = memcpy_s(buf, ctrl_log->log_length, ctrl_log->log_buffer, ctrl_log->log_length);
        g_free(ctrl_log->log_buffer);
        ctrl_log->log_buffer = NULL;
        if (securec_rv != EOK) {
            debug_log(DLOG_ERROR, "%s: memcpy_s failed, ret = %d", __FUNCTION__, securec_rv);
            g_free(buf);
            return SML_ERR_SEC_FUNC_FAILED;
        }
    }

    securec_rv = memcpy_s(buf + ctrl_log->log_length, data_len, data, data_len);
    if (securec_rv != EOK) {
        debug_log(DLOG_ERROR, "%s: memcpy_s failed, ret = %d", __FUNCTION__, securec_rv);
        g_free(buf);
        return SML_ERR_SEC_FUNC_FAILED;
    }

    ctrl_log->log_buffer = buf;
    ctrl_log->log_length = len;
    return SML_SUCCESS;
}

/*
 * Description: 申请载荷内存空间
 */
static gint32 malloc_payload_data(struct lib_cmd_param *lib_param, guint16 max_pay_load)
{
    lib_param->data = g_malloc0(max_pay_load + sizeof(struct log_rsp_head));
    if (lib_param->data == NULL) {
        debug_log(DLOG_ERROR, "%s: Malloc data failed", __FUNCTION__);
        return SML_ERR_CANNOT_ALLOC_MEM;
    }
    lib_param->data_len = (guint16)(max_pay_load + sizeof(struct log_rsp_head));
    return SML_SUCCESS;
}

/*
 * Description: 释放载荷内存空间
 */
static void free_payload_data(struct lib_cmd_param *lib_param)
{
    if (lib_param->data != NULL) {
        free(lib_param->data);
        lib_param->data = NULL;
    }
    return;
}

/*
 * Description: 解析返回的数据
 */
static gint32 parse_ret_data(struct lib_cmd_param *lib_param, struct cmd_log_info_req *req_param, guint16 index,
    guint32 *data_count, guint16 *max_pay_load)
{
    if ((index > 0) && (index != req_param->req_seq + 1)) {
        debug_log(DLOG_ERROR, "%s: req_seq check error, req_seq:%u, current req_seq:%u", __FUNCTION__,
            req_param->req_seq, index);
        return SML_ERR_DATA_INVALID;
    }

    struct log_rsp_head *head = lib_param->data;
    // 数据分片数量
    *data_count = ((head->total_size % REQ_DATA_LEN) == 0) ? (head->total_size / REQ_DATA_LEN)
                                                                : (head->total_size / REQ_DATA_LEN + 1);
    *max_pay_load = (head->max_pay_load < REQ_DATA_LEN) ? head->max_pay_load : REQ_DATA_LEN;

    // 处理下一次请求参数
    req_param->req_seq = index;
    req_param->req_offset = (*max_pay_load) * index;

    if ((index + 1) == *data_count) {  // 请求最后一片数据
        if (*max_pay_load == 0) {
            debug_log(DLOG_ERROR, "%s: max pay load = 0", __FUNCTION__);
            return SML_ERR_DATA_INVALID;
        }
        req_param->req_len = head->total_size % *max_pay_load;
        req_param->flag = 1 << FLAG_END;
    } else {
        req_param->req_len = *max_pay_load;
        req_param->flag = 1 << FLAG_MID;
    }

    return SML_SUCCESS;
}

/*
 * Description：刷dump数据到flash
 */
static gint32 set_rd_dump_send(guint32 ctrl_id)
{
    struct lib_cmd_param lib_param;
    (void)memset_s(&lib_param, sizeof(lib_param), 0, sizeof(lib_param));

    lib_param.opcode = ADM_RAID_SET;
    lib_param.subopcode = ADM_CMD_SET_DUMP;
    lib_param.card_id = ctrl_id;
    lib_param.channel = PCIE_PHYSICAL_FUCTION0;
    return process_histore_cmd(&lib_param);
}

/*
 * Description：设置收集nand_log的下标
 */
static gint32 set_nand_log_idx(guint32 ctrl_id, guint8 idx)
{
    struct lib_cmd_param lib_param;
    (void)memset_s(&lib_param, sizeof(lib_param), 0, sizeof(lib_param));
    struct cmd_set_nand_log_idx log_idx;
    (void)memset_s(&log_idx, sizeof(log_idx), 0, sizeof(log_idx));
    log_idx.idx = idx;

    lib_param.opcode = ADM_RAID_SET;
    lib_param.subopcode = ADM_CMD_SET_NAND_LOG_IDX;
    lib_param.card_id = ctrl_id;
    lib_param.channel = PCIE_PHYSICAL_FUCTION0;
    lib_param.param_len = (guint16)sizeof(struct cmd_set_nand_log_idx);

    errno_t securec_rv = memcpy_s(lib_param.cmd_param, sizeof(lib_param.cmd_param), &log_idx, sizeof(log_idx));\
    if (securec_rv != EOK) {
        debug_log(DLOG_ERROR, "%s: memcpy_s failed, ret = %d", __FUNCTION__, securec_rv);
    }

    return process_histore_cmd(&lib_param);
}

/*
 * Description: 从RAID卡获取文件
 */
static gint32 get_file_from_ctrl(guint32 ctrl_id, SML_CTRL_LOG_DATA_S *ctrl_log, guint8 collect_type, guint16 subopcode,
    guint32 max_data_count)
{
    struct cmd_log_info_req req_param;
    (void)memset_s(&req_param, sizeof(req_param), 0, sizeof(req_param));

    req_param.collect_type = collect_type;
    req_param.flag = 1 << FLAG_HEAD;

    struct lib_cmd_param lib_param;
    (void)memset_s(&lib_param, sizeof(lib_param), 0, sizeof(lib_param));

    lib_param.card_id = ctrl_id;
    lib_param.opcode = ADM_RAID_READ;
    lib_param.subopcode = subopcode;
    lib_param.param_len = (guint16)sizeof(struct cmd_log_info_req);
    lib_param.timeout_ms = HISTORE_CMD_TIMEOUT_MAX; // 日志收集的响应较慢且不允许重试，超时时间改为60000ms

    // 分片获取日志文件
    guint32 index = 0;
    guint32 data_count = 0; // 分片数量
    guint16 max_pay_load = 0;
    gint32 ret = 0;
    while (index <= data_count && index <= max_data_count) {
        ret = malloc_payload_data(&lib_param, max_pay_load);
        if (ret) {
            goto EXIT;
        }
        // 拷贝参数到lib
        errno_t securec_rv = memcpy_s(lib_param.cmd_param, sizeof(lib_param.cmd_param), &req_param, sizeof(req_param));
        if (securec_rv != EOK) {
            debug_log(DLOG_ERROR, "%s: memcpy_s cmd_param failed, ret = %d", __FUNCTION__, securec_rv);
            ret = SML_ERR_SEC_FUNC_FAILED;
            goto EXIT;
        }

        ret = process_histore_cmd(&lib_param);
        if (ret) {
            debug_log(DLOG_ERROR, "%s: process_histore_cmd failed. ret = %d", __FUNCTION__, ret);
            goto EXIT;
        }
        // 解析返回数据
        ret = parse_ret_data(&lib_param, &req_param, index, &data_count, &max_pay_load);
        if (ret) {
            goto EXIT;
        }

        if (index > 0) {
            // 保存数据
            ret = save_ret_data(&lib_param, ctrl_log);
            if (ret) {
                goto EXIT;
            }
        }
        free_payload_data(&lib_param);
        index++;
    }

EXIT:
    free_payload_data(&lib_param);
    return ret;
}

/*
 * Description: 获取RAID卡日志
 */
static gint32 get_ctrl_log(guint32 ctrl_id, SML_CTRL_LOG_DATA_S *ctrl_log)
{
    guint8 i;

    for (i = 0; i < G_N_ELEMENTS(g_log_cmd); i++) {
        if (ctrl_log->log_type == g_log_cmd[i].log_type) {
            break;
        }
    }

    if (i == G_N_ELEMENTS(g_log_cmd)) {
        debug_log(DLOG_ERROR, "%s: invalid log type = %d", __FUNCTION__, ctrl_log->log_type);
        return SML_ERR_INVALID_CMD;
    }

    gint32 ret;
    if (ctrl_log->log_type == CTRL_DUMP_FILE_TYPE) {
        // 这个日志要求获取最新的dump数据
        ret = set_rd_dump_send(ctrl_id);
        if (ret != SML_SUCCESS) {
            debug_log(DLOG_ERROR, "%s: set_rd_dump_send failed, ret = 0x%X", __FUNCTION__, ret);
            return ret;
        }
    } else if (ctrl_log->log_type == CTRL_NAND_LOG0_FILE_TYPE) {
        ret = set_nand_log_idx(ctrl_id, 0);
        if (ret != SML_SUCCESS) {
            debug_log(DLOG_ERROR, "%s: set_nand_log_idx failed, ret = 0x%X", __FUNCTION__, ret);
            return ret;
        }
    } else if (ctrl_log->log_type == CTRL_NAND_LOG1_FILE_TYPE) {
        ret = set_nand_log_idx(ctrl_id, 1);
        if (ret != SML_SUCCESS) {
            debug_log(DLOG_ERROR, "%s: set_nand_log_idx failed, ret = 0x%X", __FUNCTION__, ret);
            return ret;
        }
    }

    return get_file_from_ctrl(ctrl_id, ctrl_log, g_log_cmd[i].collect_type, g_log_cmd[i].subopcode,
        g_log_cmd[i].max_data_count);
}

gint32 histore_ctrl_operations(guint32 ctrl_id, guint8 operation, gpointer param, guint32 param_length)
{
    gint32 retval;

    switch (operation) {
        case CTRL_OPERATION_ENABLE_JBOD:
            if (param == NULL || param_length == 0) {
                return SML_ERR_NULL_DATA;
            }
            retval = set_ctrl_property_operations(ctrl_id, operation, param, param_length);
            break;

        case CTRL_OPERATION_RESTORE_DEFAULT:
            retval = set_ctrl_restore_default(ctrl_id);
            break;
        case CTRL_OPERATION_DUMP_LOG:
            if (param == NULL || param_length == 0) {
                return SML_ERR_NULL_DATA;
            }
            retval = get_ctrl_log(ctrl_id, (SML_CTRL_LOG_DATA_S *)param);
            break;
        case CTRL_OPERATION_DISABLE_COPYBACK:
            retval = set_ctrl_enable_copyback(ctrl_id, param);
            break;
        case CTRL_OPERATION_ENABLE_SMART_COPYBACK:
            retval = set_ctrl_enable_smart_copyback(ctrl_id, param);
            break;
        case CTRL_OPERATION_ENABLE_CC:
            retval = set_ctrl_enable_consis_check(ctrl_id, (SML_CTRL_SET_CONSIS_CHECK_PARAM *)param);
            break;
        case CTRL_OPERATION_IMPORT_FOREIGN_CONFIG:
            retval = ctrl_import_foreign_config(ctrl_id);
            break;
        case CTRL_OPERATION_CLEAR_FOREIGN_CONFIG:
            retval = ctrl_clear_foreign_config(ctrl_id);
            break;
        case CTRL_OPERATION_SET_SLOW_DISK_DETECTION:
            retval = set_ctrl_slow_disk_detection_mode(ctrl_id, (SML_CTRL_SET_SLOW_DISK_DETECTTECTION_MODE *)param);
            break;
        default:
            retval = SML_ERR_CTRL_OPERATION_NOT_SUPPORT;
            break;
    }

    return retval;
}

/*
 * Description: 发送命令给histore lib获取bbu信息
 */
static gint32 get_bbu_info(guint32 ctrl_id, struct cmd_supercapacitor_info *bbu_info)
{
    struct lib_cmd_param lib_param;
    (void)memset_s(&lib_param, sizeof(lib_param), 0, sizeof(lib_param));
    lib_param.opcode = ADM_RAID_READ;
    lib_param.subopcode = ADM_CMD_GET_SC_INFO;
    lib_param.card_id = ctrl_id;
    lib_param.channel = PCIE_PHYSICAL_FUCTION0;
    lib_param.data_len = (guint16)sizeof(struct cmd_supercapacitor_info);
    lib_param.data = bbu_info;
    return process_histore_cmd(&lib_param);
}
gint32 histore_get_ctrl_health(guint32 ctrl_id, gpointer data)
{
    if (data == NULL) {
        return SML_ERR_NULL_DATA;
    }
    struct cmd_supercapacitor_info bbu_info;
    (void)memset_s(&bbu_info, sizeof(bbu_info), 0, sizeof(bbu_info));
    gint32 ret = get_bbu_info(ctrl_id, &bbu_info);
    if (ret != SML_SUCCESS) {
        debug_log(DLOG_DEBUG, "get_bbu_info failed, ret = %d", ret);
        return ret;
    }
    SML_CTRL_HEALTH_DATA_S *ctrl = (SML_CTRL_HEALTH_DATA_S *)data;
    ctrl->bbu_present = bbu_info.present;
    struct cmd_controller_status ctrl_status;
    (void)memset_s(&ctrl_status, sizeof(ctrl_status), 0, sizeof(ctrl_status));

    gint32 retval = get_ctrl_status(ctrl_id, &ctrl_status);
    if (retval != SML_SUCCESS) {
        debug_log(DLOG_ERROR, "%s get_ctrl_status failed, ret = %d", __FUNCTION__, retval);
        return retval;
    }

    ctrl->ctrl_hw_err = ctrl_status.board_hw_err;
    ctrl->ctrl_clk_err = ctrl_status.board_clk_err;
    ctrl->ctrl_power_err = ctrl_status.board_power_err;
    ctrl->ctrl_capacity_err = ctrl_status.board_capacity_err;
    ctrl->ctrl_flash_err = ctrl_status.board_flash_err;
    return SML_SUCCESS;
}

gint32 histore_get_ctrl_bbu_status(guint32 ctrl_id, gpointer data)
{
    if (data == NULL) {
        return SML_ERR_NULL_DATA;
    }
    struct cmd_supercapacitor_info bbu_info;
    (void)memset_s(&bbu_info, sizeof(bbu_info), 0, sizeof(bbu_info));
    gint32 ret = get_bbu_info(ctrl_id, &bbu_info);
    if (ret != SML_SUCCESS) {
        debug_log(DLOG_ERROR, "get_bbu_info failed, ret = %d", ret);
        return ret;
    }
    SML_BBU_STATUS_S *bbu = (SML_BBU_STATUS_S *)data;
    bbu->temperature = (gint8)(bbu_info.temperature & 255);
    debug_log(DLOG_DEBUG, "%s bbu temp value is %d, ctrl_id = %d, raw_bbu_data = %d", __FUNCTION__,
        bbu->temperature, ctrl_id, bbu_info.temperature);
    bbu->present = bbu_info.present;
    bbu->temperature_high = ((bbu_info.sc_status) & BIT(1)) ? 1 : 0; // 电容模组温度过高告警（bit1置1有效）
    if ((bbu_info.learn_status & BIT(0)) == 0) { // 电压过低和电容模组剩余容量低在自学习时不会置位，自学习完成后根据结果置位
        bbu->voltage_low = ((bbu_info.sc_status) & BIT(2)) ? 1 : 0; // 电容模组电压过低告警（bit2 置1有效）
        bbu->remaining_capacity_low = ((bbu_info.sc_status) & BIT(3)) ? 1 : 0; // 电容模组剩余容量低（bit3 置1有效）
    }
    bbu->replacepack = ((bbu_info.sc_status) & BIT(4)) ? 1 : 0; // 需要更换（bit4 置1有效）
    bbu->no_space = ((bbu_info.sc_status) & BIT(5)) ? 1 : 0; // 没有空间备份cache（bit5 置1有效）
    bbu->pack_missing = ((bbu_info.sc_status) & BIT(6)) ? 1 : 0; // 电容不在位（bit6 置1有效）
    bbu->learn_cycle_failed = ((bbu_info.learn_status) & BIT(2)) ? 1 : 0; // 自学习失败（自学习状态bit2位置1有效）
    bbu->learn_cycle_timeout = ((bbu_info.learn_status) & BIT(3)) ? 1 : 0; //  自学习超时（自学习状态bit3位置1有效）
    strncpy_s(bbu->type, sizeof(bbu->type), bbu_info.device_name, strlen(bbu_info.device_name));
    return SML_SUCCESS;
}
