-- Copyright (c) 2024 Huawei Technologies Co., Ltd.
-- 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.

local NVME_MI_OPTIONS = require 'nvme.nvme_mi_protocol.nvme_mi_def'
local nvme_admin_command = require 'nvme.nvme_mi_protocol.nvme_mi_admin_command'

local nvme_admin_command_process = {}

-- 判断该NVMe盘是否支持uuidlist
function nvme_admin_command_process.check_support_uuid_by_identify_ctrl(obj)
    local ret = nvme_admin_command.identify_ctrl(obj)
    if not ret then
        return false
    end
    local parse_ret = NVME_MI_OPTIONS.controller_data_structure_response:unpack(ret, true)
    if not parse_ret or not parse_ret.ctratt then
        return false
    end
    return (parse_ret.ctratt & NVME_MI_OPTIONS.UUID_LIST_SUPPORT) ~= 0
end

-- 判断指定opcode是否支持uuid
function nvme_admin_command_process.check_specified_opcode_support_uuid(obj, opcode)
    local ret = nvme_admin_command.get_support_effects_log(obj)
    if not ret then
        return false
    end
    local parse_ret = NVME_MI_OPTIONS.commands_supported_effects_log_response:unpack(ret, true)
    if not parse_ret then
        return false
    end
    local admin_command_support_bin = string.sub(parse_ret.acs_list, opcode * NVME_MI_OPTIONS.ACS_DATA_LENGTH + 1,
        opcode * NVME_MI_OPTIONS.ACS_DATA_LENGTH + 1 + NVME_MI_OPTIONS.ACS_DATA_LENGTH)
    local admin_command_support =
        NVME_MI_OPTIONS.commands_supported_effects_data_structure:unpack(admin_command_support_bin, true)
    if not admin_command_support or not admin_command_support.uuid_selection_supported then
        return false
    end
    return admin_command_support.uuid_selection_supported == 1
end

-- 获取指定uuid的uuid_index
function nvme_admin_command_process.get_specified_uuid_index(obj, uuid_ll, uuid_lh, uuid_hl, uuid_hh)
    local ret = nvme_admin_command.identify_uuid_list(obj)
    if not ret then
        return false
    end
    local parse_ret = NVME_MI_OPTIONS.uuid_list_response:unpack(ret, true)
    if not parse_ret or not parse_ret.uuid_list then
        return false
    end
    local uuid_entry = NVME_MI_OPTIONS.uuid_list_entry:unpack(parse_ret.uuid_list, true)
    if not uuid_entry then
        return false
    end
    local uuid_index = 1
    while uuid_index < NVME_MI_OPTIONS.UUID_ENTRY_NUM do
        if uuid_entry.uuid_ll == uuid_ll and uuid_entry.uuid_lh == uuid_lh and
            uuid_entry.uuid_hl == uuid_hl and uuid_entry.uuid_hh == uuid_hh then
            break;
        end
        uuid_entry = NVME_MI_OPTIONS.uuid_list_entry:unpack(uuid_entry.next_uuid_entry, true)
        if not uuid_entry then
            return false
        end
        uuid_index = uuid_index + 1
    end
    return uuid_index < NVME_MI_OPTIONS.UUID_ENTRY_NUM and uuid_index or false
end

-- 判断是否可以不填充uuid_index获取hw_defined smart log
function nvme_admin_command_process.check_support_hw_defined_without_uuid(obj)
    local ret = nvme_admin_command.get_hw_defined_smart_log(obj)
    return ret and true or false
end

return nvme_admin_command_process