-- 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 mctp_lib = require 'mctp_lib'
local log = require 'mc.logging'
local cm = require 'common_def'

local MODULE_NAME_STORAGE_MGNT <const> = 'Storage'
local MCTP_MSG_TYPE_VENDOR_PCI <const> = 0x7E
local HUAWEI_VENDER_ID <const> = 0x1E81
local PMC_VENDER_ID <const> = 0x9005

local manager_mctp = {}
manager_mctp.__index = manager_mctp

function manager_mctp.is_pmc_raid(type_id)
    if type_id == cm.PMC_3152_8I_SMART_RAID or type_id == cm.PMC_2100_8I_SMART_HBA then
        return true
    end
    return false
end

function manager_mctp.new(bus, controller)
    local phy_addr = mctp_lib.bdf_to_phy_addr(controller.DevBus, controller.DevDevice,
        controller.DevFunction)
    log:notice('[Storage] DevBus: %d, DevDevice: %d, DevFunction: %d', controller.DevBus,
        controller.DevDevice, controller.DevFunction)
    controller.Phyaddr = phy_addr
    local raid_vendor_id = manager_mctp.is_pmc_raid(controller.TypeId) and PMC_VENDER_ID or HUAWEI_VENDER_ID
    return setmetatable({
        id = controller.Id,
        eid = 0, -- eid 由 endpoint 提供，本地不需要保存
        bus = bus,
        phy_addr = phy_addr,
        vendor_id = raid_vendor_id
    }, manager_mctp)
end

-- 向驱动注册消息类型与设备的绑定关系
function manager_mctp:register_ctrl_mctp_transport()
    local ok, endpoint, transport = pcall(mctp_lib.get_endpoint_and_transport, self.bus,
        MODULE_NAME_STORAGE_MGNT, self.phy_addr, MCTP_MSG_TYPE_VENDOR_PCI)
    if not ok then
        error(string.format('[Storage] Failed to register mctp transport, return %s', endpoint))
    end
    log:notice('[Storage] Successfully register_ctrl_mctp_transport')
    self.transport = transport
end

return manager_mctp
