-- 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 bs = require 'mc.bitstring'

local nvme_mi_defs = {
    NVME_MI_MESSAGE_TYPE = {
        CONTROL_PRIMITIVE  = 0X00,
        NVME_MI_COMMAND    = 0X01,
        NVME_ADMIN_COMMAND = 0X02,
        PCIE_COMMAND       = 0X04
    },
    NVME_ADMIN_COMMANDS_OPCODE = {
        NVME_ADMIN_DELETE_SUBMISSION_QUEUE = 0X00,
        NVME_ADMIN_CREATE_SUBMISSION_QUEUE = 0X01,
        NVME_ADMIN_GET_LOG_PAGE            = 0X02,
        NVME_ADMIN_DELETE_COMPLETION_QUEUE = 0X04,
        NVME_ADMIN_CREATE_COMPLETION_QUEUE = 0X05,
        NVME_ADMIN_IDENTIFY                = 0X06,
        NVME_ADMIN_ABORT_CMD               = 0X08,
        NVME_ADMIN_SET_FEATURES            = 0X09,
        NVME_ADMIN_GET_FEATURES            = 0X0A,
        NVME_ADMIN_ASYNC_EVENT             = 0X0C,
        NVME_ADMIN_NS_MGMT                 = 0X0D,
        NVME_ADMIN_ACTIVATE_FW             = 0X10,
        NVME_ADMIN_DOWNLOAD_FW             = 0X11,
        NVME_ADMIN_DEV_SELF_TEST           = 0X14,
        NVME_ADMIN_NS_ATTACH               = 0X15,
        NVME_ADMIN_KEEP_ALIVE              = 0X18,
        NVME_ADMIN_DIRECTIVE_SEND          = 0X19,
        NVME_ADMIN_DIRECTIVE_RECV          = 0X1A,
        NVME_ADMIN_VIRTUAL_MGMT            = 0X1C,
        NVME_ADMIN_NVME_MI_SEND            = 0X1D,
        NVME_ADMIN_NVME_MI_RECV            = 0X1E,
        NVME_ADMIN_CAPACITY_MGMT           = 0X20,
        NVME_ADMIN_LOCKDOWN_CMD            = 0X24,
        NVME_ADMIN_DBBUF                   = 0X7C,
        NVME_ADMIN_FORMAT_NVM              = 0X80,
        NVME_ADMIN_SECURITY_SEND           = 0X81,
        NVME_ADMIN_SECURITY_RECV           = 0X82,
        NVME_ADMIN_SANITIZE_NVM            = 0X84,
        NVME_ADMIN_GET_LBA_STATUS          = 0X86,
    },
    LOG_PAGE_IDENTIFIERS = {
        SUPPORTED_LOG_PAGES                   = 0x00,
        ERROR_INFORMATION                     = 0x01,
        SMART_INFORMATION                     = 0x02, -- SMART / Health Information
        FIRMWARE_SLOT_INFORMATION             = 0x03,
        CHANGED_NAMESPACE_LIST                = 0x04,
        COMMANDS_SUPPORTED_AND_EFFECTS        = 0x05,
        DEVICE_SELF_TEST                      = 0x06,
        TELEMETRY_HOST_INITIATED              = 0x07,
        TELEMETRY_CONTROLLER_INITIATED        = 0x08,
        ENDURANCE_GROUP_INFORMATION           = 0x09,
        PREDICTABLE_LATENCY_PER_NVM_SET       = 0x0A,
        PREDICTABLE_LATENCY_EVENT_AGGREGATE   = 0x0B,
        ASYMMETRIC_NAMESPACE_ACCESS           = 0x0C,
        PERSISTENT_EVENT_LOG                  = 0x0D,
        LBA_STATUS                            = 0x0E,
        ENDURANCE_GROUP_EVENT_AGGREGATE       = 0x0F,
        FEATURE_IDENTIFIERS_SUPPORTED_EFFECTS = 0x12,
        BOOT_PARTITION                        = 0x15,
        DISCOVERY                             = 0x70,
        RESERVATION_NOTIFICATION              = 0x80,
        SANITIZE_STATUS                       = 0x81,
        ZONED_NAMESPACE                       = 0xBF
    },
    LOG_TO_STRING = {
        [0x00] = "Supported Log Pages",
        [0x01] = "Error Information",
        [0x02] = "SMART Information",
        [0x03] = "Firmware Slot Information",
        [0x04] = "Changed Namespace List",
        [0x05] = "Commands Supported and Effects",
        [0x06] = "Device Self-test",
        [0x07] = "Telemetry Host-Initiated",
        [0x08] = "Telemetry Controller-Initiated",
        [0x09] = "Endurance Group Information",
        [0x0A] = "Predictable Latency Per NVM Set",
        [0x0B] = "Predictable Latency Event Aggregate",
        [0x0C] = "Asymmetric Namespace Access",
        [0x0D] = "Persistent Event Log",
        [0x0E] = "LBA Status Information",
        [0x0F] = "Endurance Group Event Aggregate",
        [0x12] = "FID Supported and Effects",
        [0x15] = "Boot Partition",
        [0x70] = "Discovery",
        [0x80] = "Reservation Notification",
        [0x81] = "Sanitize Status",
        [0xBF] = "Host Identifier"
    },
    FID_SUPPORTED_EFFECTS = {
        FSUPP         = 1 << 0,
        UDCC          = 1 << 1,
        NCC           = 1 << 2,
        NIC           = 1 << 3,
        CCC           = 1 << 4,
        UUID_SEL_SUP  = 1 << 19,
        SCOPE_SHIFT   = 20,
        SCOPE_MASK    = 0xfff,
        NS_SCOPE      = 1 << 0,
        CTRL_SCOPE    = 1 << 1,
        NVM_SET_SCOPE = 1 << 2,
        ENDGRP_SCOPE  = 1 << 3,
        DOMAIN_SCOPE  = 1 << 4,
        NSS_SCOPE     = 1 << 5,
    },
    MI_COMMAND_OPCODE = {
        READ_MI_DATA_STRUCTRUE = 0,
        NVM_SUBSYSTEM_HEALTH_STATUS_POLL = 1,
        CONTROLLER_HEALTH_STATUS_POLL = 2,
        CONFIGURATION_SET = 3,
        CONFIGURATION_GET = 4,
        VPD_READ = 5,
        RESET = 6
    },
    NVME_STATUS_TO_STRING = {
        [0x00] = "SUCCESS: The command completed successfully",
        [0x01] = "INVALID_OPCODE: The associated command opcode field is not valid",
        [0x02] = "INVALID_FIELD: A reserved coded value or an unsupported value in a defined field",
        [0x03] = "CMDID_CONFLICT: The command identifier is already in use",
        [0x04] = "DATA_XFER_ERROR: Error while trying to transfer the data or metadata",
        [0x05] = "POWER_LOSS: Command aborted due to power loss notification",
        [0x06] = "INTERNAL: The command was not completed successfully due to an internal error",
        [0x07] = "ABORT_REQ: The command was aborted due to a Command Abort request",
        [0x08] = "ABORT_QUEUE: The command was aborted due to a Delete I/O Submission Queue request",
        [0x09] = "FUSED_FAIL: The command was aborted due to the other command in a fused operation failing",
        [0x0A] = "FUSED_MISSING: The command was aborted due to a Missing Fused Command",
        [0x0B] = "INVALID_NS: The namespace or the format of that namespace is invalid",
        [0x0C] = "CMD_SEQ_ERROR: The command was aborted due to a protocol violation in a multicommand sequence",
        [0x0D] = "SGL_INVALID_LAST: The command includes an invalid SGL Last Segment or SGL Segment descriptor"
    },
    NVME_MI_CONFIG_IDENT = {
        SMBUS_I2C_FREQUENCY = 1,
        HEALTH_STATUS_CHANGE = 2,
        MCTP_TRANSMISSION_UNIT_SIZE = 3
    },
    DATA_STRUCTURE_TYPE = {
        NVM_SUBSYSTEM_INFORMATION = 0,
        PORT_INFORMATION = 1,
        CONTROLLER_LIST = 2,
        CONTROLLER_INFORMATION = 3,
        OPTIONALLY_SUPPORTED_COMMAND_LIST = 4,
        MANAGEMENT_ENDPOINT_BUFFER_COMMAND_SUPPORT_LIST = 5
    },
    log_request = bs.new([[<<
        opcode:8,
        flags:8,
        ctrl_id:16,
        nsid:32,
        _:32,
        _:32,
        _:32,
        _:32,
        data_offset:32,
        data_len:32,
        _:32,
        _:32,
        cdw10:32,
        cdw11:32,
        cdw12:32,
        cdw13:32,
        cdw14:32,
        _:32
        >>]]),
    smart_log_response = bs.new([[<<
        rsvd:3/unit:8,
        cdw0:4/unit:8,
        cdw1:4/unit:8,
        cdw3:4/unit:8,
        critical_warning:8,
        temperature:16,
        avail_spare:8,
        spare_thresh:8,
        percent_used:8,
        endu_grp_crit_warn_sumry:8,
        rsvd7:8/unit:8,
        rsvd15:8/unit:8,
        rsvd23:8/unit:8,
        rsvd32:8,
        data_units_read_l:8/unit:8,
        data_units_read_h:8/unit:8,
        data_units_written_l:8/unit:8,
        data_units_written_h:8/unit:8,
        host_reads_l:8/unit:8,
        host_reads_h:8/unit:8,
        host_writes_l:8/unit:8,
        host_writes_h:8/unit:8,
        ctrl_busy_time_l:8/unit:8,
        ctrl_busy_time_h:8/unit:8,
        power_cycles_l:8/unit:8,
        power_cycles_h:8/unit:8,
        power_on_hours_l:8/unit:8,
        power_on_hours_h:8/unit:8,
        unsafe_shutdowns_l:8/unit:8,
        unsafe_shutdowns_h:8/unit:8,
        media_errors_l:8/unit:8,
        media_errors_h:8/unit:8,
        num_err_log_entries_l:8/unit:8,
        num_err_log_entries_h:8/unit:8,
        warning_temp_time:32,
        critical_comp_time:32,
        temp_sensor1:16,
        temp_sensor2:16,
        temp_sensor3:16,
        temp_sensor4:16,
        temp_sensor5:16,
        temp_sensor6:16,
        temp_sensor7:16,
        temp_sensor8:16,
        thm_temp1_trans_count:32,
        thm_temp2_trans_count:32,
        thm_temp1_total_time:32,
        thm_temp2_total_time:32,
        rsvd232/string
        >>]]),
    fw_log_response = bs.new([[<<
        rsvd:3/unit:8,
        cdw0:4/unit:8,
        cdw1:4/unit:8,
        cdw3:4/unit:8,
        afi:8,
        resv:56,
        frs1:8/little-string,
        frs2:8/little-string,
        frs3:8/little-string,
        frs4:8/little-string,
        frs5:8/little-string,
        frs6:8/little-string,
        frs7:8/little-string,
        rsvd64/string
        >>]]),
    buffur_size_4_response = bs.new('<<data:32, info/binary>>'),
    error_log_response = bs.new([[<<
        error_count:8/unit:8,
        sqid:16,
        cmdid:16,
        status_field:16,
        parm_error_location:16,
        lba:8/unit:8,
        nsid:4/unit:8,
        vsia:8,
        trtype:8,
        rsvd1:16,
        csi:8/unit:8,
        trtype_spec_info:16,
        resv2:8/unit:8,
        resv2:8/unit:8,
        resv2:6/unit:8,
        info/string
        >>]]),
    log_response = bs.new([[<<
        rsvd:3/unit:8,
        cdw0:4/unit:8,
        cdw1:4/unit:8,
        cdw3:4/unit:8,
        data/string
        >>]]),
    nvmemi_command_request = bs.new([[<<
        opcode:8,
        rsvd1:8,
        rsvd2:16,
        dword0:32,
        dword1:32
        >>]]),
    mi_ctrl_health_status_rsp = bs.new([[<<
        rsvd2:16,
        entries:8,
        data/string
        >>]]),
    mi_ctrl_health_status_data = bs.new([[<<
        ctlid:16,
        csts:16,
        ctemp:16,
        pdlu:8,
        spare:8,
        cwarn:8,
        chsc:16,
        rsvd:5/unit:8,
        info/string
        >>]]),
    unit_size_rsp = bs.new([[<<
        size:8,
        rsvd2:2/unit:8
        >>]]),
    subsystem_info = bs.new([[<<
        rsvd3:24,
        nump:8,
        mjr:8,
        mnr:8,
        subsyscap:8,
        rsvd/string
        >>]]),
    subsystem_health_status = bs.new([[<<
        rsvd3:24,
        nss:8,
        sw:8,
        ctemp:8,
        pdlu:8,
        ccs:16,
        rsvd/string
        >>]])
}

return nvme_mi_defs