-- 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 class = require 'mc.class'
local log = require 'mc.logging'
local cmn = require 'common'

local c_eth_device = class()

-- 等待PcieAddrInfo对应的源端连接器状态build_ready, 超时120s
local function retry_get_src_connector(target_c)
    local retry = 120
    while retry > 0 do
        if target_c.src_connector and target_c.src_connector.build_ready then
            log:notice("[EthDevice] target_c: %s, find src: %s, start_lane: %s",
                target_c.mds_obj.name, target_c.src_connector.mds_obj.name, target_c.start_lane)
            return target_c.src_connector, target_c.start_lane
        end
        retry  =retry -1
        cmn.skynet.sleep(100)
    end
end

-- addr_obj: 网卡对应的PcieAddrInfo
-- 从源端连接器同步一个EthDevice的bcu_idx、SocketID、DieId、ControllerIndex、laneId和Bus信息
function c_eth_device:sync_bdf_info(target_c)
    cmn.skynet.fork(function()
        local src_c, start_lane = retry_get_src_connector(target_c)
        if not src_c or not src_c.die_idxs or not src_c.bus_nums then
            self.sync_ready = true
            log:error("[EthDevice] cannot find connectors")
            return
        end
        self.mds_obj.LaneId = self.mds_obj.LaneId + start_lane
        self.die_id = src_c.die_idxs[self.mds_obj.LaneId + 1] or 0
        self.mds_obj.SocketID = self.die_id >> 8
        self.mds_obj.ControllerIndex = src_c.c_idxs[self.mds_obj.LaneId + 1] or 0
        self.mds_obj.Bus = src_c.bus_nums[self.mds_obj.LaneId + 1] or 255
        self.bcu_idx = src_c.bcu_index
        self.sync_ready = true
        log:notice("[EthDevice] EthDevice %s, sync_ready, SocketID %s, ControllerIndex %s, DieId %s, Bus %s",
            self.mds_obj.name, self.mds_obj.SocketID, self.mds_obj.ControllerIndex, self.die_id, self.mds_obj.Bus)
    end)
end

local function get_system_id(path)
    return tonumber(string.match(path, '/bmc/kepler/Systems/(%d+)'))
end

function c_eth_device:init()
    self.system_id = get_system_id(self.mds_obj.path)
end

function c_eth_device:ctor(mds_obj, position, bus)
    self.mds_obj = mds_obj
    self.position = position
    self.bus = bus
    self.die_id = 0
    self.sync_ready = false
end

return c_eth_device