-- 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 CX5 = require 'hardware_config.CX5'

local CX7 = {
    properties = {
        OpticalGetIdentifier = {
            protocol = 'ncsi_mellanox',
            action = 'on_demand',
            request = {
                -- ReqPayload
                -- {
                -- u32 manufacturer_id
                -- u8 cmd_mellanox
                -- u8 mellanox_cmd_id
                -- u8 parameter
                -- u8 reserved
                ----- 从这里开始表示
                -- u8 i2c_address
                -- u8 page_number 0
                -- u16 dev_address
                -- u8 page_lock_field 0
                -- u8 operation 0
                -- u16 transfer_size 0x0100
                -- =======结束==========
                -- u32 checksum
                -- }
                cmd_mellanox = 0x00,
                mellanox_cmd_id = 0x13,
                parameter = 0x11,
                extra_cmd = 0x0,

                data = bs.new([[<<
                i2c_address:8,
                page_number:8,
                dev_address:16,
                page_lock_field:8,
                operation:8,
                transfer_size:16
            >>]]):pack({
                    i2c_address = 0x50,
                    page_number = 0x0,
                    dev_address = 0x0,
                    page_lock_field = 0x0,
                    operation = 0x0,
                    transfer_size = 0x0100
                }, true)
            },

            response = function(data)
                -- RspPayload
                -- {
                -- u16 response_code
                -- u16 reason_code
                -- u32 manufacturer_id
                -- u8 cmd_mellanox
                -- u8 mellanox_cmd_id
                -- u8 parameter
                ---- 从这里开始表示----
                -- u8 reserved
                -- u8 i2c_addres
                -- u8 page_number
                -- u16 dev_address 
                -- u8  page_lock_field 0
                -- u8 operation 0
                -- u16 transfer size 0x0100
                -- u32*12 dword
                -- =======结束==========
                -- u32 checksum
                -- }
                local r = bs.new([[<<
                    reserved:8,
                    i2c_addres:8,
                    page_number:8,
                    dev_address:16,
                    page_lock_field:8,
                    operation:8,
                    transfer_size:16,
                    identifier:16
                >>]]):unpack(data, true)
                -- 协商的光模块协议版本
                -- 1E 或1B：CMIS
                -- 其他 SFF-8636
                if not r then
                    return 'OpticalTempSFF8636'
                end
                local identifier = r.identifier & 0xff
                local IDENTIFIER_CMIS <const> = 0x1e
                local SFF8024_ID_DSFP <const> = 0x1b

                if identifier == IDENTIFIER_CMIS or identifier == SFF8024_ID_DSFP then
                    return 'OpticalTempCMIS50'
                end
                return 'OpticalTempSFF8636'
            end
        },
        -- SFF-8636
        -- u8 i2c_addres  0x50
        -- u16 dev_address  0x1600
        OpticalTempSFF8636 = {
            protocol = 'ncsi_mellanox',
            action = 'on_schedule',
            period_in_sec = 2,
            request = {
                cmd_mellanox = 0x00,
                mellanox_cmd_id = 0x13,
                parameter = 0x11,
                extra_cmd = 0x0,
                data = bs.new([[<<
                i2c_address:8,
                page_number:8,
                dev_address:16,
                page_lock_field:8,
                operation:8,
                transfer:16
            >>]]):pack({
                    i2c_address = 0x50,
                    page_number = 0x0,
                    dev_address = 0x1600,
                    page_lock_field = 0x0,
                    operation = 0x0,
                    transfer = 0x0100 -- 取一个字节数据
                }, true)
            },

            response = function(data)
                -- RspPayload
                -- {
                -- u16 response_code
                -- u16 reason_code
                -- u32 manufacturer_id
                -- u8 cmd_mellanox
                -- u8 mellanox_cmd_id
                -- u8 parameter
                ---- 从这里开始表示----
                -- u8 reserved
                -- u8 i2c_addres
                -- u8 page_number
                -- u16 dev_address 
                -- u8 page_lock_field 0
                -- u8 operation 0
                -- u16 transfer_size 0x0100
                -- u32 dword
                -- =======结束==========
                -- u32 checksum
                -- }
                local r = bs.new([[<<
                    reserved:8,
                    i2c_addres:8,
                    page_number:8,
                    dev_address:16,
                    page_lock_field:8,
                    operation:8,
                    transfer_size:16,
                    temperature:16
                >>]]):unpack(data, true)
                if not r then
                    return nil
                end
                return r.temperature & 0xff
            end
        },
        -- CMIS-5.0
        -- 0x50
        -- 0x0e00
        OpticalTempCMIS50 = {
            protocol = 'ncsi_mellanox',
            action = 'on_schedule',
            period_in_sec = 2,
            request = {
                cmd_mellanox = 0x00,
                mellanox_cmd_id = 0x13,
                parameter = 0x11,
                extra_cmd = 0x0,
                data = bs.new([[<<
                    i2c_address:8,
                    page_number:8,
                    dev_address:16,
                    page_lock_field:8,
                    operation:8,
                    transfer:16
                >>]]):pack({
                    i2c_address = 0x50,
                    page_number = 0x0,
                    dev_address = 0x0e00,
                    page_lock_field = 0x0,
                    operation = 0x0,
                    transfer = 0x0100 -- 取一个字节数据
                }, true)
            },

            response = function(data)
                -- RspPayload
                -- {
                -- u16 response_code
                -- u16 reason_code
                -- u32 manufacturer_id
                -- u8 cmd_mellanox
                -- u8 mellanox_cmd_id
                -- u8 parameter
                ---- 从这里开始表示----
                -- u8 reserved
                -- u8 i2c_addres
                -- u8 page_number
                -- u16 dev_address 
                -- u8 page_lock_field 0
                -- u8 operation 0
                -- u16 transfer_size 0x0100
                -- u32 dword
                -- =======结束==========
                -- u32 checksum
                -- }
                local r = bs.new([[<<
                        reserved:8,
                        i2c_addres:8,
                        page_number:8,
                        dev_address:16,
                        page_lock_field:8,
                        operation:8,
                        transfer_size:16,
                        temperature:16
                    >>]]):unpack(data, true)
                if not r then
                    return nil
                end
                return r.temperature & 0xff
            end
        }
    }
}

return {
    smbus = nil,
    mctp = function(endpoint)
        local cx5 = CX5.mctp(endpoint)
        for k, v in pairs(CX7.properties) do
            cx5.properties[k] = v
        end
    return cx5
    end
}

