-- 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 = {
    BUFFER_SIZE_512 = 0x200,
    BUFFER_SIZE_4096 = 0x1000,
    NVME_NSID_ALL = 0xffffffff,
    UUID_LIST_SUPPORT = 0x200,
    ACS_DATA_LENGTH = 4,
    UUID_ENTRY_NUM = 128,
    HW_DEFINED_UUID_LL = 0x9CB6772E,
    HW_DEFINED_UUID_LH =0xed113475,
    HW_DEFINED_UUID_HL = 0xBDA82CAE,
    HW_DEFINED_UUID_HH = 0xC15980D2,
    HW_DEFINED_MAGIC = 0x84215aa51248,
    HW_DEFINED_ENTRY_LEN = 12,
    NOT_SUPPORT_HW_DEFINED = 0,
    SUPPORT_HW_DEFINED_WITH_UUID = 1,
    SUPPORT_HW_DEFINED_WITHOUT_UUID = 2,

    DATA_LENGTH = {
        HW_DEFINED_SMART_LOG = 3072,
        SUPPORT_EFFECTS_LOG = 4096,
        SMART_LOG = 512,
        IDENTIFY = 4096
    },

    LOG_PAGE_PARAM = {
        log_id = 0,
        lpo = 0,
        nsid = 0,
        uuid_idx = 0,
        csi = 0,
        data_len = 0,
        lsi = 0,
        ot = false,
        rae = false,
        lsp = 0,
        date_len = 0,
        data_offset = 0
    },

    IDENTIFY_PARAM = {
        nsid = 0,
        cdw10 = 0,
        cdw11 = 0,
        cdw12 = 0,
        cdw13 = 0,
        cdw14 = 0
    },


    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,
        HW_DEFINED_SMART_LOG                  = 0xEF
    },

    -- Controller or Namespace Structure
    CNS_VALUES = {
        ID_CNS_NS                   = 0x00,
        ID_CNS_CTRL                 = 0x01,
        ID_CNS_NS_ACTIVE_LIST       = 0x02,
        ID_CNS_NS_DESC_LIST         = 0x03,
        ID_CNS_NVMSET_LIST          = 0x04,
        ID_CNS_CSI_ID_NS            = 0x05,
        ID_CNS_CSI_ID_CTRL          = 0x06,
        ID_CNS_CSI_NS_ACTIVE_LIST   = 0x07,
        ID_CNS_CS_INDEPENDENT_ID_NS = 0x08,
        ID_CNS_NS_PRESENT_LIST      = 0x10,
        ID_CNS_NS_PRESENT           = 0x11,
        ID_CNS_CTRL_NS_LIST         = 0x12,
        ID_CNS_CTRL_LIST            = 0x13,
        ID_CNS_PRIMARY_CTRL_CAPS    = 0x14,
        ID_CNS_SCNDRY_CTRL_LIST     = 0x15,
        ID_CNS_NS_GRANULARITY       = 0x16,
        ID_CNS_UUID_LIST            = 0x17,
        ID_CNS_DOMAIN_LIST          = 0x18,
        ID_CNS_ENDURANCE_GROUP_ID   = 0x19,
        ID_CNS_CSI_NS_PRESENT_LIST  = 0x1A,
        ID_CNS_CSI_NS_PRESENT       = 0x1B,
        ID_CNS_CSI                  = 0x1C
    },
    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
    },

    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"
    },
    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
    },
    NVME_NO_LOG_LSP = 0,
    NVME_LSP_CREATE = 0,
    response_status = {
        [0x2] = 'Internal Error',
        [0x3] = 'Invalid Command Opcode',
        [0x4] = 'Invalid Parameter',
        [0x5] = 'Invalid Command Size',
        [0x6] = 'Invalid Command Input Data Size',
        [0x7] = 'Access Denied',
        [0x20] = 'VPD Updates Exceeded',
        [0x21] = 'PCIe Inaccessible',
        [0x22] = 'Management Endpoint Buffer Cleared Due to Sanitize',
        [0x23] = 'Enclosure Services Failure',
        [0x24] = 'Enclosure Services Transfer Failure',
        [0x25] = 'Enclosure Failure',
        [0x26] = 'Enclosure Services Transfer Refused',
        [0x27] = 'Unsupported Enclosure Function',
        [0x28] = 'Enclosure Services Unavailable',
        [0x29] = 'Enclosure Degraded',
        [0x2a] = 'Sanitize In Progress'
    },
    responss_message = bs.new([[<<
        status:8,
        data/string
        >>]]),
    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:6/unit:8,
        data_units_written_h:6/unit:8,
        rsvd4:4/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
        >>]]),
    nvmemi_command_request_extend = bs.new([[<<
        opcode:8,
        rsvd1:8,
        rsvd2:16,
        dword0:32,
        dword1:32,
        data/string
        >>]]),
    nvmemi_command_response = bs.new([[<<
        status:8,
        nvmersq:24,
        data/string
        >>]]),
    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
        >>]]),
    telemetry_log_page_rsp = bs.new([[<<
        rsvd:3/unit:8,
        cdw0:4/unit:8,
        cdw1:4/unit:8,
        cdw3:4/unit:8,
        lpi:8,
        rsvd1:32,
        iee_oui:24,
        dalb1:16,
        dalb2:16,
        dalb3:16,
        rsvd2:16,
        dalb4:32,
        rsvd3/string
        >>]]),
    controller_data_structure_response = bs.new([[<<
        rsvd:3/unit:8,
        cdw0:4/unit:8,
        cdw1:4/unit:8,
        cdw3:4/unit:8,
        vid:16,
        ssvid:16,
        sn:20/little-string,
        mn:40/little-string,
        fr:8/little-string,
        rab:8,
        ieee:3/unit:8,
        cmic:8,
        mdts:8,
        cntlid:16,
        ver:4/unit:8,
        rtd3r:4/unit:8,
        rtd3e:4/unit:8,
        oaes:4/unit:8,
        ctratt:4/unit:8,
        rsvdstr/string
        >>]]),
    commands_supported_effects_log_response = bs.new([[<<
        rsvd:3/unit:8,
        cdw0:4/unit:8,
        cdw1:4/unit:8,
        cdw3:4/unit:8,
        acs_list/string
        >>]]),
    commands_supported_effects_data_structure = bs.new([[<<
        csupp:1,
        lbcc:1,
        ncc:1,
        nic:1,
        ccc:1,
        rsvd:11,
        cse:3,
        uuid_selection_supported:1,
        rsvd:12
        >>]]),
    uuid_list_response = bs.new([[<<
        rsvd:3/unit:8,
        cdw0:4/unit:8,
        cdw1:4/unit:8,
        cdw3:4/unit:8,
        _:32,
        _:32,
        _:32,
        _:32,
        _:32,
        _:32,
        _:32,
        _:32,
        uuid_list/string
        >>]]),
    uuid_list_entry = bs.new([[<<
        _:32,
        _:32,
        _:32,
        _:32,
        uuid_ll:4/unit:8,
        uuid_lh:4/unit:8,
        uuid_hl:4/unit:8,
        uuid_hh:4/unit:8,
        next_uuid_entry/string
        >>]]),
    hw_defined_smart_log_response = bs.new([[<<
        rsvd:3/unit:8,
        cdw0:4/unit:8,
        cdw1:4/unit:8,
        cdw3:4/unit:8,
        magic_header:12/string,
        attr_list:1512/string,
        rsvd/string
        >>]]),
    hw_defined_smart_log_magic_header = bs.new([[<<
        flag:1/unit:8,
        version:2/unit:8,
        rsvd:2/unit:8,
        identifier:6/unit:8,
        rsvd1:1/unit:8
        >>]]),
    attr_entry_data_structure = bs.new([[<<
        attr_id:8,
        flag:2/unit:8,
        current_value:8,
        worst_value:8,
        raw_value:6/unit:8,
        rsvd:8,
        rest/string
        >>]]),
    controller_list_format = bs.new([[<<
        rsvd3:24,
        number_of_identifiers:16,
        ctrl_id:16,
        rsvd/string
        >>]]),
}

return nvme_mi_defs