-- Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
--
-- this file licensed under the 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 log = require 'mc.logging'
local mmc = {}

local CSD_SLC_USED_LIFE_LOCATION<const> = 268
local CSD_MLC_USED_LIFE_LOCATION<const> = 269
local CSD_PRE_EOL_INFO_LOCATION<const> = 267

local MMC_REG_TYPE_E = {
    ['MMC_EXT_CSD'] = 0, -- emmc ext_csd寄存器
    ['MMC_CID'] = 1, -- emmc cid寄存器
    ['MMC_CSD'] = 2 -- emmc csd寄存器
}

function mmc:new()
    return mmc
end

-- cid寄存器信息
local mmc_cid_info = {72, 74, 1, 144, 97, 52, 71, 56, 33, 142, 161, 146, 175, 182, 209, 18}
-- csd寄存器信息
local mmc_csd_info = {50, 0 ,15, 208, 255, 3, 89, 143, 239, 255, 255, 255, 35, 64 ,64, 138}
-- ext_csd寄存器
local mmc_ext_csd_info = {
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 3, 128, 14, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 0, 48, 0, 0, 48,
    0, 0, 16, 0, 0, 1, 0, 181, 1, 0, 7, 1, 1, 2, 0, 0, 21, 31, 32, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2,
    0, 13, 0, 0, 0, 0, 8, 0, 2, 0, 87, 31, 10, 3, 221, 221, 0, 0, 0, 10, 10, 10, 10, 10, 10, 1, 128, 14, 193, 0, 23,
    18, 23, 7, 5, 16, 1, 3, 1, 8, 32, 0, 7, 166, 166, 85, 3, 0, 0, 0, 0, 211, 211, 0, 1, 90, 8, 0, 0, 0, 0, 25, 25, 0,
    16, 0, 0, 221, 55, 51, 49, 48, 51, 53, 49, 55, 37, 80, 8, 8, 8, 1, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 16, 0, 3, 3, 0, 5, 3, 3, 1, 63, 63, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0
}
function mmc:read(info)
    if info.mmc_reg_type_v == MMC_REG_TYPE_E.MMC_EXT_CSD then
        if info.mmc_reg_offset == CSD_PRE_EOL_INFO_LOCATION then
            return string.char(1) -- pre-eof状态值
        elseif info.mmc_reg_offset == 0 then
            return string.char(table.unpack(mmc_ext_csd_info))
        end
        return string.char(7) -- 模拟已使用寿命
    elseif info.mmc_reg_type_v == MMC_REG_TYPE_E.MMC_CID then
        return string.char(table.unpack(mmc_cid_info))
    elseif info.mmc_reg_type_v == MMC_REG_TYPE_E.MMC_CSD then
        return string.char(table.unpack(mmc_csd_info))
    end
end

local write_time = 0
local write_byte = 0
local access_count = 0 --访问次数
local increment = 1024 * 1024 * 1024 -- 模拟1G写入量
function mmc:get_tbw(info)
    if info.mmc_clear_flag == 1 then
        write_time = 0
        write_byte = 0
        access_count = 0
    else
        if access_count >= 25 then --读取25从之后写入量减少
            increment = 1024 * 1024
        end
        access_count = access_count + 1
        write_time = write_time + 3600 -- 模拟1小时
        write_byte = write_byte + increment -- 模拟数据量
        info.write_time = write_time
        info.write_byte = write_byte
    end
    log:info('mmc get_tbw: info.write_time = %d, info.write_byte = %d, access_count = %d' .. 'increment = %d',
        write_time, write_byte, access_count, increment)
end

local hynix_health_report = {
    7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 0, 0, 0, 89, 8, 0, 0, 89, 5, 0, 0, 9, 7, 0, 0, 8, 0, 0, 89, 5, 0, 0, 9, 7, 0,
    0, 8, 0, 0, 89, 5, 0, 0, 9, 7, 89, 0, 0, 0, 89, 8, 0, 0, 89, 5, 0, 0, 9, 7, 0, 0, 8, 0, 0, 2
}

function mmc:get_hynix_health_report()
    if hynix_health_report[61] < 256 then -- 每次访问擦写次数 + 1，数据偏移位置为61
        hynix_health_report[61] = hynix_health_report[61] + 1
    end
    log:info('mmc get_hynix_health_report: erase_count = %d', hynix_health_report[61] + hynix_health_report[62] * 256)
    return string.char(table.unpack(hynix_health_report))
end
mmc.MMC_REG_INFO_S = {}
mmc.MMC_REG_INFO_S.new = function()
    return {
        mmc_reg_type_v = 0, -- emmc颗粒寄存器类型
        mmc_reg_offset = 0, -- emmc颗粒寄存器的偏移(除了est_csd寄存器其他两个是0)
        length = 0, -- 需要获取的emmc颗粒寄存器的字节长度
        buf = '' -- 获取的数据
    }
end

mmc.MMC_WRITE_ALLINFO_S = {}
mmc.MMC_WRITE_ALLINFO_S.new = function()
    return {
        mmc_clear_flag = 0, -- 是否清除前一次的统计数据(时间和写入量)
        write_time = 0, -- 统计的总的时间
        write_byte = 0 -- 在统计总的时间范围内的写入量
    }
end

return mmc