// +FHDR------------------------------------------------------------
//                 Copyright (c) 2022 SmartLogic.
//                       ALL RIGHTS RESERVED
// -----------------------------------------------------------------
// Filename      : ecs_rfm_spu1_oam.c
// Author        : huanfeng.wang
// Created On    : 2023-05-22
// Last Modified :
// -----------------------------------------------------------------
// Description:
//
//
// -FHDR------------------------------------------------------------

#include "log_server.h"
#include "spu_hw_queue.h"
#include "ape_csu.h"
#include "ucp_port.h"
#include "ucp_utility.h"
#include "ucp_printf.h"
#include "ecs_rfm_spu1_oam.h"
#include "log_server.h"
#include "ucp_drv_common.h"
#include "cpri_delay.h"
#include "ecs_rfm_dm_mgt.h"
#include "app_interface.h"

#define RFM_TEST_OAM_MSG_SIZE   (8)
#define RFM_MSG_TYPE            (0)

extern void phy_oam_msg_proc(uint32_t u32msg_addr, uint32_t u32msg_size);

OamMsgTransferHeader_t        *g_oam_msg_ptr                          = NULL;
SpuOamBaseDelaySetRsp_t       *g_oam_base_delay_set_rsp_ptr           = NULL;
SpuOamBaseDelayQryRsp_t       *g_oam_base_delay_qry_rsp_ptr           = NULL;
SpuOamFiberDelayQryRsp_t      *g_oam_fiber_delay_qry_rsp_ptr          = NULL;
SpuOamFrameHeadOffsetRsp_t    *g_oam_frame_head_offset_rsp_ptr        = NULL;
SpuOamFrameHeadOffsetQryRsp_t *g_oam_frame_head_offset_qry_rsp_ptr = NULL;

void oam_msg_init(void)
{
    uint8_t  u8core_id = (uint8_t)get_core_id();

    EcsRfmDmLocalMgt_t* pEcsDmLocalMgt      = get_ecs_rfm_dm_local_mgt();
    g_oam_msg_ptr                           = (OamMsgTransferHeader_t *)pEcsDmLocalMgt->pOamMsgPtr;
    g_oam_base_delay_set_rsp_ptr            = (SpuOamBaseDelaySetRsp_t  *)pEcsDmLocalMgt->pOamBaseDelaySetRspPtr;
    g_oam_base_delay_qry_rsp_ptr            = (SpuOamBaseDelayQryRsp_t  *)pEcsDmLocalMgt->pOamBaseDelayQryRspPtr;
    g_oam_fiber_delay_qry_rsp_ptr           = (SpuOamFiberDelayQryRsp_t *)pEcsDmLocalMgt->pOamFiberDelayQryRspPtr;
    g_oam_frame_head_offset_rsp_ptr         = (SpuOamFrameHeadOffsetRsp_t *)pEcsDmLocalMgt->pOamFrameHeadOffsetRspPtr;
    g_oam_frame_head_offset_qry_rsp_ptr     = (SpuOamFrameHeadOffsetQryRsp_t *)pEcsDmLocalMgt->pOamFrameHeadOffsetQryRspPtr;

    memset_ucp(g_oam_base_delay_set_rsp_ptr->u8rsv,      0, 2);
    memset_ucp(g_oam_base_delay_qry_rsp_ptr->u8rsv,      0, 2);
    memset_ucp(g_oam_fiber_delay_qry_rsp_ptr->u8rsv, 0, 2);
    memset_ucp(g_oam_fiber_delay_qry_rsp_ptr->u8rsv, 0, 1);
    debug_write(DBG_DDR_COMMON_IDX(u8core_id, 37), g_oam_msg_ptr);
    debug_write(DBG_DDR_COMMON_IDX(u8core_id, 56), g_oam_base_delay_set_rsp_ptr);/*0xb7e016e0*/
    return;
}


void oam_msg_proc(uint32_t u32msg_addr, uint32_t u32msg_size)
{
    uint32_t msg_type   = 0;
    uint32_t i          = 0;
    uint32_t msg_buf    = do_read(u32msg_addr);
    uint32_t msg_size   = do_read(u32msg_addr + 4);
    uint8_t  u8core_id = (uint8_t)get_core_id();
    SpuOamBaseDelaySetReq_t    *oam_base_delay_set_ptr      = NULL;
    SpuOamBaseDelayQryReq_t    *oam_base_delay_qry_ptr      = NULL;
    SpuOamFiberDelayQryReq_t   *oam_fiber_delay_qry_ptr     = NULL;
    SpuOamFrameHeadOffsetReq_t *oam_frame_head_offset_ptr   = NULL;


    debug_write(DBG_DDR_COMMON_IDX(u8core_id, 36), 0x12345678);
    memset((void *)g_oam_msg_ptr, 0, sizeof(OamMsgTransferHeader_t));
    debug_write(DBG_DDR_COMMON_IDX(u8core_id, 38), msg_size);

    ape_csu_dma_1D_G2L_ch2ch3_transfer(msg_buf, (uint64_t)((uint32_t)g_oam_msg_ptr - 0x100000), msg_size+12, 2, 1);
    debug_write(DBG_DDR_COMMON_IDX(u8core_id, 39), msg_buf);
    debug_write(DBG_DDR_COMMON_IDX(u8core_id, 40), g_oam_msg_ptr->numMsg);
    debug_write(DBG_DDR_COMMON_IDX(u8core_id, 41), g_oam_msg_ptr->msgType);
    UCP_PRINT_ERROR("oam_msg_proc numMsg:%d msg_type:0x%x msg_size:%d\n", g_oam_msg_ptr->numMsg, g_oam_msg_ptr->msgType, msg_size);

    for(i = 0; i < g_oam_msg_ptr->numMsg; i++)
    {
        msg_type = g_oam_msg_ptr->msgType;
        
        switch(msg_type)
        {
            case SPU_OAM_BASE_DELAY_SET_REQ:
                UCP_PRINT_ERROR("oam_msg_proc numMsg:%d i:%d msg_type:0x%x\n", g_oam_msg_ptr->numMsg, i, msg_type);
                oam_base_delay_set_ptr = (SpuOamBaseDelaySetReq_t *)((uint8_t *)g_oam_msg_ptr + sizeof(OamMsgTransferHeader_t));
                oam_base_delay_proc(oam_base_delay_set_ptr, g_oam_msg_ptr);
                break;
            case SPU_OAM_BASE_DELAY_QRY_REQ:
                UCP_PRINT_ERROR("oam_msg_proc numMsg:%d i:%d msg_type:0x%x\n", g_oam_msg_ptr->numMsg, i, msg_type);
                oam_base_delay_qry_ptr = (SpuOamBaseDelayQryReq_t *)((uint8_t *)g_oam_msg_ptr + sizeof(OamMsgTransferHeader_t));
                oam_base_qry_proc(oam_base_delay_qry_ptr, g_oam_msg_ptr);
                break;
            case SPU_OAM_FIBER_DELAY_QRY_REQ:
                UCP_PRINT_ERROR("oam_msg_proc numMsg:%d i:%d msg_type:0x%x\n", g_oam_msg_ptr->numMsg, i, msg_type);
                oam_fiber_delay_qry_ptr = (SpuOamFiberDelayQryReq_t *)((uint8_t *)g_oam_msg_ptr + sizeof(OamMsgTransferHeader_t));
                oam_fiber_delay_proc(oam_fiber_delay_qry_ptr, g_oam_msg_ptr);
                break;
            case SPU_OAM_FRAME_HEAD_OFFSET_REQ:
                UCP_PRINT_ERROR("oam_msg_proc numMsg:%d i:%d msg_type:0x%x\n", g_oam_msg_ptr->numMsg, i, msg_type);
                oam_frame_head_offset_ptr = (SpuOamFrameHeadOffsetReq_t *)((uint8_t *)g_oam_msg_ptr + sizeof(OamMsgTransferHeader_t));
                oam_frame_head_offset_proc(oam_frame_head_offset_ptr, g_oam_msg_ptr);
                break;
            case SPU_OAM_FRAME_HEAD_OFFSET_QRY_REQ:
                UCP_PRINT_ERROR("oam_msg_proc numMsg:%d i:%d msg_type:0x%x\n", g_oam_msg_ptr->numMsg, i, msg_type);
                oam_frame_head_offset_qry_proc(g_oam_msg_ptr);
                break;
            default:
                phy_oam_msg_proc(u32msg_addr, u32msg_size);
                break;
        }
    }

    return;
}

void oam_base_delay_proc(SpuOamBaseDelaySetReq_t *spu_oam_base_delay_set_ptr, OamMsgTransferHeader_t *spu_oam_msg_ptr)
{
    uint8_t u8core_id = (uint8_t)get_core_id();
    SpuOamBaseDelaySetRsp_t *oam_base_delay_set_rsp_ptr = NULL;

    
    if(NULL == spu_oam_base_delay_set_ptr)
    {
        return;
    }
    
    /*调用接口获取配置结果 0:fail 1:ok*/
    oam_base_delay_set_rsp_ptr = (SpuOamBaseDelaySetRsp_t *)set_cpri_link_delay((stCpriSetLinkDelay *)spu_oam_base_delay_set_ptr);
    g_oam_base_delay_set_rsp_ptr->u8result         = oam_base_delay_set_rsp_ptr->u8result;
    g_oam_base_delay_set_rsp_ptr->u8fiber_port     = oam_base_delay_set_rsp_ptr->u8fiber_port;

    debug_write(DBG_DDR_COMMON_IDX(u8core_id, 42), g_oam_base_delay_set_rsp_ptr->u8result);/*0xb7e016a8*/
    debug_write(DBG_DDR_COMMON_IDX(u8core_id, 43), spu_oam_base_delay_set_ptr->u32ul_data_frame_offset);
    debug_write(DBG_DDR_COMMON_IDX(u8core_id, 44), spu_oam_base_delay_set_ptr->u32dl_frame_offset);
    debug_write(DBG_DDR_COMMON_IDX(u8core_id, 45), spu_oam_base_delay_set_ptr->u32ul_frame_offset);

    UCP_PRINT_ERROR("oam_base_delay_proc cellIndex:%d\n",     spu_oam_msg_ptr->cellIndex);
    UCP_PRINT_ERROR("oam_base_delay_proc u8result:%d\n",      g_oam_base_delay_set_rsp_ptr->u8result);
    UCP_PRINT_ERROR("oam_base_delay_proc u8fiber_port:%d\n", g_oam_base_delay_set_rsp_ptr->u8fiber_port);
    UCP_PRINT_ERROR("oam_base_delay_proc u32ul_data_frame_offset:0x%x\n",  spu_oam_base_delay_set_ptr->u32ul_data_frame_offset);
    UCP_PRINT_ERROR("oam_base_delay_proc u32dl_frame_offset:0x%x\n",  spu_oam_base_delay_set_ptr->u32dl_frame_offset);
    UCP_PRINT_ERROR("oam_base_delay_proc u32ul_frame_offset:0x%x\n", spu_oam_base_delay_set_ptr->u32ul_frame_offset);

    oam_spu_send_msg(spu_oam_msg_ptr->cellIndex, (uint32_t)g_oam_base_delay_set_rsp_ptr, sizeof(SpuOamBaseDelaySetRsp_t), SPU_OAM_BASE_DELAY_SET_RSP);

    return;
}

void oam_base_qry_proc(SpuOamBaseDelayQryReq_t        *spu_oam_base_delay_qry_ptr, OamMsgTransferHeader_t *spu_oam_msg_ptr)
{
    uint8_t u8core_id = (uint8_t)get_core_id();

    if(NULL == spu_oam_base_delay_qry_ptr)
    {
        return;
    }
    
    /*调用接口获取配置结果0:fail 1:ok*/
    get_cpri_link_delay(spu_oam_base_delay_qry_ptr->u8fiber_port,     (stCpriGetLinkDelay*)g_oam_base_delay_qry_rsp_ptr);

    debug_write(DBG_DDR_COMMON_IDX(u8core_id, 46), g_oam_base_delay_qry_rsp_ptr->u8result);/*0xb7e016b8*/
    debug_write(DBG_DDR_COMMON_IDX(u8core_id, 47), g_oam_base_delay_qry_rsp_ptr->u32ul_data_frame_offset);
    debug_write(DBG_DDR_COMMON_IDX(u8core_id, 48), g_oam_base_delay_qry_rsp_ptr->u32dl_frame_offset);
    debug_write(DBG_DDR_COMMON_IDX(u8core_id, 49), g_oam_base_delay_qry_rsp_ptr->u32ul_frame_offset);

    UCP_PRINT_ERROR("oam_base_qry_proc u8fiber_port:%d u8result:%d\n", \
                   g_oam_base_delay_qry_rsp_ptr->u8fiber_port, g_oam_base_delay_qry_rsp_ptr->u8result);
    UCP_PRINT_ERROR("oam_base_qry_proc dl:0x%x ul:0x%x\n", \
                   g_oam_base_delay_qry_rsp_ptr->u32dl_frame_offset, g_oam_base_delay_qry_rsp_ptr->u32ul_frame_offset);
    UCP_PRINT_ERROR("oam_base_qry_proc u32ul_data_frame_offset:0x%x\n",  g_oam_base_delay_qry_rsp_ptr->u32ul_data_frame_offset);

    oam_spu_send_msg(spu_oam_msg_ptr->cellIndex, (uint32_t)g_oam_base_delay_qry_rsp_ptr, sizeof(SpuOamBaseDelayQryRsp_t), SPU_OAM_BASE_DELAY_QRY_RSP);

    return;
}

void oam_fiber_delay_proc(SpuOamFiberDelayQryReq_t *spu_oam_fiber_delay_qry_ptr, OamMsgTransferHeader_t *spu_oam_msg_ptr)
{
    uint8_t u8core_id = (uint8_t)get_core_id();

    if(NULL == spu_oam_fiber_delay_qry_ptr)
    {
        return;
    }

    /*调用接口获取配置结果0:fail 1:ok*/
    get_cpri_rndtrip_delay(spu_oam_fiber_delay_qry_ptr->u8fiber_port, (stCpriGetRndDelay*)g_oam_fiber_delay_qry_rsp_ptr);

    debug_write(DBG_DDR_COMMON_IDX(u8core_id, 50), g_oam_fiber_delay_qry_rsp_ptr->u8fiber_port);/*0xb7e016c8*/
    debug_write(DBG_DDR_COMMON_IDX(u8core_id, 51), g_oam_fiber_delay_qry_rsp_ptr->u8result);
    debug_write(DBG_DDR_COMMON_IDX(u8core_id, 52), g_oam_fiber_delay_qry_rsp_ptr->u32t14_val);
    UCP_PRINT_LOG("oam_fiber_delay_proc u8fiber_port:%d \n", g_oam_fiber_delay_qry_rsp_ptr->u8fiber_port);
    UCP_PRINT_LOG("oam_fiber_delay_proc u8result:%d \n",      g_oam_fiber_delay_qry_rsp_ptr->u8result);
    UCP_PRINT_LOG("oam_fiber_delay_proc u32t14_val:0x%x\n",     g_oam_fiber_delay_qry_rsp_ptr->u32t14_val);

    oam_spu_send_msg(spu_oam_msg_ptr->cellIndex, (uint32_t)g_oam_fiber_delay_qry_rsp_ptr, sizeof(SpuOamFiberDelayQryRsp_t), SPU_OAM_FIBER_DELAY_QRY_RSP);

    return;
}

void oam_frame_head_offset_proc(SpuOamFrameHeadOffsetReq_t *spu_oam_frame_head_offset_ptr, OamMsgTransferHeader_t *spu_oam_msg_ptr)
{
    uint8_t u8core_id = (uint8_t)get_core_id();
    SpuOamFrameHeadOffsetRsp_t *oam_frame_head_offset_rsp_ptr = NULL;

    if(NULL == spu_oam_frame_head_offset_ptr)
    {
        UCP_PRINT_ERROR("oam_frame_head_offset_proc is null\n");
        return;
    }

    /*调用接口帧头偏移配置结果0:fail 1:ok*/
    oam_frame_head_offset_rsp_ptr = (SpuOamFrameHeadOffsetRsp_t *)set_frame_head_offset((stCpriFrameHeadOffsetReq*)spu_oam_frame_head_offset_ptr);
    g_oam_frame_head_offset_rsp_ptr->u8result = oam_frame_head_offset_rsp_ptr->u8result;
    
    debug_write(DBG_DDR_COMMON_IDX(u8core_id, 56), g_oam_frame_head_offset_rsp_ptr->u8result);
    UCP_PRINT_ERROR("oam_frame_head_offset_proc u8result:%d \n",  g_oam_frame_head_offset_rsp_ptr->u8result);

    oam_spu_send_msg(spu_oam_msg_ptr->cellIndex, (uint32_t)g_oam_frame_head_offset_rsp_ptr, sizeof(SpuOamFrameHeadOffsetRsp_t), SPU_OAM_FRAME_HEAD_OFFSET_RSP);

    return;
}

void oam_frame_head_offset_qry_proc(OamMsgTransferHeader_t *spu_oam_msg_ptr)
{
    uint8_t u8core_id = (uint8_t)get_core_id();

    if(NULL == spu_oam_msg_ptr)
    {
        UCP_PRINT_ERROR("spu_oam_msg_ptr is null\n");
        return;
    }

    /*调用接口帧头偏移配置结果0:fail 1:ok*/
    get_cpri_framehead_offset((stCpriGetFrameHeadOffset *)g_oam_frame_head_offset_qry_rsp_ptr);
    
    debug_write(DBG_DDR_COMMON_IDX(u8core_id, 57), g_oam_frame_head_offset_qry_rsp_ptr->u16frame_head_offset);
    UCP_PRINT_ERROR("oam_frame_head_offset_qry_proc u8result:%d u16frame_head_offset:0x%x \n", g_oam_frame_head_offset_qry_rsp_ptr->u8result, g_oam_frame_head_offset_qry_rsp_ptr->u16frame_head_offset);

    oam_spu_send_msg(spu_oam_msg_ptr->cellIndex, (uint32_t)g_oam_frame_head_offset_qry_rsp_ptr, sizeof(SpuOamFrameHeadOffsetQryRsp_t), SPU_OAM_FRAME_HEAD_OFFSET_QRY_RSP);

    return;
}

static inline uint32_t oam_spu_fill_msg_header(uint8_t inst_id, char* buf, uint32_t size, uint32_t msgType)
{
    OamMsgTransferHeader_t header;
    header.numMsg = 1;
    header.cellIndex = inst_id;
    header.msgType = msgType;
    header.msgLen  = size + sizeof(OamMsgTransferHeader_t);
    uint8_t u8core_id = (uint8_t)get_core_id();

    memcpy_ucp(buf, &header, sizeof(OamMsgTransferHeader_t));
     __ucps2_synch(0);
    debug_write(DBG_DDR_COMMON_IDX(u8core_id, 57), buf);/*0xb7e016e4*/

    uint32_t dst_addr = (uint32_t)(buf + sizeof(OamMsgTransferHeader_t));
    
    return dst_addr;
}

static inline int32_t oam_spu_send_msg(uint8_t inst_id, uint32_t src_addr, uint32_t size, uint32_t msgType)
{
    uint8_t u8core_id = (uint8_t)get_core_id();

    if (0 == size) {
        return SUCCESS;
    }
    uint32_t len = size+sizeof(OamMsgTransferHeader_t);

    char* buf;
    uint32_t availableSize,offset;

    uint16_t cu_flag = C_PLANE;
    HandleId_t handler;
    handler.port_id = get_ucp_port_id();
    handler.inst_id = inst_id;
    handler.type_id = OAM;
    
    int32_t ret = msg_transfer_send_start(handler.value);
    ret = msg_transfer_alloc_msg(handler.value, cu_flag, len, &buf, &availableSize, &offset);
    if (SUCCESS != ret)
    {
        UCP_PRINT_ERROR("oam_spu_send_msg ret[0x%08x]", ret);
        return ret;
    }

    uint32_t dst_addr = oam_spu_fill_msg_header(inst_id, buf, size, msgType);

    //ape_csu_dma_1D_G2L_ch2ch3_transfer((uint64_t)((uint32_t)(src_addr-0x100000)), dst_addr, size, inst_id, 1);
    ape_csu_dma_1D_L2G_ch2ch3_transfer((uint64_t)((uint32_t)(src_addr-0x100000)), dst_addr, size, inst_id, 1);
    //memcpy_ucp(dst_addr, src_addr, size);

    debug_write(DBG_DDR_COMMON_IDX(u8core_id, 53), dst_addr);/*0xb7e016d4*/
    debug_write(DBG_DDR_COMMON_IDX(u8core_id, 54), src_addr);/*dm物理地址：rfm1:0x07220000 + (addr - 0x220000)*/
    debug_write(DBG_DDR_COMMON_IDX(u8core_id, 55), buf);

    ret = msg_transfer_send_msg(handler.value, cu_flag, (uint8_t *)buf, offset, len);
    ret = msg_transfer_send_end(handler.value);

    UCP_PRINT_LOG("oam_spu_send_msg buf:%p len:%d\n", buf, len);

    return ret;
}

void oam_msg_proc_test(uint32_t u32msg_addr, uint32_t u32msg_size)
{
    int32_t  ret        = 0;
    char     *addr      = NULL;
    uint32_t msg_buf    = do_read(u32msg_addr);
    uint32_t msg_size   = do_read(u32msg_addr + 4);
    uint8_t  u8core_id = (uint8_t)get_core_id();

    debug_write(DBG_DDR_COMMON_IDX(u8core_id, 36), 0x1234abcd);//0xb7e01690
    memset((void *)g_oam_msg_ptr, 0, sizeof(OamMsgTransferHeader_t));	
    debug_write(DBG_DDR_COMMON_IDX(u8core_id, 38), msg_size);

    ape_csu_dma_1D_G2L_ch2ch3_transfer(msg_buf, (uint64_t)((uint32_t)g_oam_msg_ptr - 0x100000), msg_size+12, 2, 1);
    debug_write(DBG_DDR_COMMON_IDX(u8core_id, 39), msg_buf);
    debug_write(DBG_DDR_COMMON_IDX(u8core_id, 40), g_oam_msg_ptr->numMsg);
    debug_write(DBG_DDR_COMMON_IDX(u8core_id, 41), g_oam_msg_ptr->msgType);
    UCP_PRINT_LOG("oam_msg_proc numMsg:%d msg_type:0x%x msg_size:%d\n", g_oam_msg_ptr->numMsg, g_oam_msg_ptr->msgType, msg_size);

    /* RFM0接收消息后发给APE1 */
    addr = osp_alloc_msg(RFM_TEST_OAM_MSG_SIZE);
    if (NULL == addr)
    {
        debug_write(DBG_DDR_COMMON_IDX(u8core_id, 42), 0xabcdef);
        return;
    }

    do_write(addr, (uint32_t)msg_buf);
    ret = osp_send_msg((uint32_t)(addr),
                        RFM_TEST_OAM_MSG_SIZE,
                        RFM_MSG_TYPE,
                        10,     // src que id
                        1,      // dst que id
                        40,     // src task id
                        40);    // dst task id

    if (0 != ret)
    {
        debug_write(DBG_DDR_COMMON_IDX(u8core_id, 43), 0x12ab34cd);
        return;
    }
    
    debug_write(DBG_DDR_COMMON_IDX(u8core_id, 44), 0x5678abcd);
    
    return;
}


