// +FHDR------------------------------------------------------------
//                 Copyright (c) 2022 SmartLogic.
//                       ALL RIGHTS RESERVED
// -----------------------------------------------------------------
// Filename      : test.c
// Author        : xianfeng.du
// Created On    : 2022-11-25
// Last Modified :
// -----------------------------------------------------------------
// Description:
//
//
// -FHDR------------------------------------------------------------

#include <stddef.h>
#include <string.h>
#include <sys/time.h>
#include <unistd.h>

#include "typedef.h"
#include "ucp_printf.h"
#include "msg_transfer_mem.h"
#include "pet_sm_mgt.h"
#include "ucp_handshake.h"
#include "ospShell.h"
#include "ospLog.h"
#include "ospCfgToBin.h"
#include "drv_init.h"

uint32_t slot_ind_flag = 0;
uint32_t slot_ind_time_flag = 0;
uint32_t  g_slot_time = 0;
uint32_t gu32_value = 0;
uint32_t gu32_tick_receive_ctrl = 0;
uint32_t gu32_tick_from_tx_ctrl = 0;

uint32_t rx_callback_data(const char* buf,uint32_t payloadSize)
{
    uint32_t stc_cnt = read_stc_local_timer();

    uint32_t value = *(uint32_t *)buf;
    uint16_t sfn = value >> 16;
    uint16_t slot = value & 0xffff;

    uint32_t tick_from_tx_ctrl = *(uint32_t *)(buf+4);

    slot_ind_flag = 1;
    gu32_value = value;
    gu32_tick_receive_ctrl = stc_cnt;
    gu32_tick_from_tx_ctrl = tick_from_tx_ctrl;
    uint32_t diff = stc_cnt - tick_from_tx_ctrl;
    //UCP_PRINT_LOG("a72_rx[%d], ape_tx[%d],offset[%d]",stc_cnt,tick_from_tx_ctrl,diff);
    //UCP_PRINT_LOG("qNO[%d],sfn[%d],slot[%d]",UCP4008_TRAFFIC_NR_eMBB_DATA,sfn,slot);

    if(0 == slot_ind_time_flag)
    {
        slot_ind_time_flag = 1;
        diff = 500000;
    }
    else
    {
        diff = stc_cnt - g_slot_time;
    }
    g_slot_time = stc_cnt;

    if ((diff > 520000) || (diff < 480000))
    {
        UCP_PRINT_ERROR("qNO[%d],sfn[%d],slot[%d],diff[%d]",UCP4008_TRAFFIC_NR_eMBB_DATA,sfn,slot,diff);
    }

    //EcsSmLocalMgt_t* pEcsSmLocalMgt = get_ecs_sm_local_mgt();
    ///MsgQueueCommonInfo_t* chCommon = pEcsSmLocalMgt->pUlQueue[0][UCP4008_TRAFFIC_NR_eMBB_DATA];
    //UCP_PRINT_DEBUG("rx_callback_data chCommon info alloc[%d],in[%d],out[%d]",chCommon->alloc,chCommon->in,chCommon->out);

    return payloadSize;
}

uint32_t rx1_callback_data(const char* buf,uint32_t payloadSize)
{
    return payloadSize;
}

uint32_t rx_callback_ctrl(const char* buf,uint32_t payloadSize)
{
#if 0
    EcsSmLocalMgt_t* pEcsSmLocalMgt = get_ecs_sm_local_mgt();
    MsgQueueCommonInfo_t* chCommon = pEcsSmLocalMgt->pUlQueue[0][UCP4008_TRAFFIC_NR_eMBB_CTRL];
    UCP_PRINT_DEBUG("rx_callback_ctrl chCommon info alloc[%d],in[%d],out[%d]",chCommon->alloc,chCommon->in,chCommon->out);
#endif
    return payloadSize;
}

static inline void get_msg_transfer_info(uint16_t port_index, uint16_t inst_id, uint16_t transfer_type, transfer_type_info_s* transfer_type_info_ptr)
{
    queue_info_s c_plane,u_plane;

    switch (transfer_type) {
        case CU_SPLIT:
            c_plane.rx_block_size = 0x25800;
            c_plane.rx_block_num = 32;
            c_plane.rx_callback = rx_callback_ctrl;
            c_plane.tx_block_size = 0x8000;
            c_plane.tx_block_num = 8;
            c_plane.tx_callback = NULL;

            u_plane.rx_block_size = 0x28000;
            u_plane.rx_block_num = 8;
            //u_plane.rx_callback = rx_callback_data;
            if (0 == inst_id)
            {
                u_plane.rx_callback = rx_callback_data;
            }
            else
            {
                u_plane.rx_callback = rx1_callback_data;
            }
            u_plane.tx_block_size = 0x28000;
            u_plane.tx_block_num = 8;
            u_plane.tx_callback = NULL;

            transfer_type_info_ptr->queue_cplane_info = c_plane;
            transfer_type_info_ptr->queue_uplane_info = u_plane;
            break;
        case OAM:
            c_plane.rx_block_size = 0x100000;
            c_plane.rx_block_num = 32;
            c_plane.rx_callback = rx_callback_oam;
            c_plane.tx_block_size = 0x8000;
            c_plane.tx_block_num = 8;
            c_plane.tx_callback = NULL;

            transfer_type_info_ptr->queue_cplane_info = c_plane;
            break;
        default:
            UCP_PRINT_ERROR("get_msg_queue_cfg doesn't support transfer_type[%d] .",transfer_type);
            break;
    }

    return;
}

static inline void msg_transfer_cfg(void)
{
    uint8_t port_id = 0;
    uint16_t inst_id = 0;
    uint16_t transfer_type = 0;
    int32_t handle_id = 0;
    transfer_type_info_s transfer_type_info;

    for (inst_id=0; inst_id<MAX_INSTANCE_NUM; inst_id++) {
        /*********************************transfer_type = CU_SPLIT**********************************/
        transfer_type = CU_SPLIT;
        get_msg_transfer_info(port_id,inst_id,transfer_type, &transfer_type_info);
        handle_id = msg_transfer_init(port_id, transfer_type, inst_id, &transfer_type_info);
        if (handle_id < 0) {
            UCP_PRINT_ERROR("phy_cfg_init transfer_type:CU_SPLIT, handle_id[0x%08x] error.",handle_id);
        }

        /*********************************transfer_type = OAM**********************************/
        transfer_type = OAM;
        get_msg_transfer_info(port_id,inst_id,transfer_type, &transfer_type_info);
        handle_id = msg_transfer_init(port_id, transfer_type, inst_id, &transfer_type_info);
        if (handle_id < 0) {
            UCP_PRINT_ERROR("phy_cfg_init transfer_type:OAM, handle_id[0x%08x] error.",handle_id);
        }
    }

    PetSmLocalMgt_t* pPetSmLocalMgt = get_pet_sm_local_mgt();
    MsgQueueLocalMgt_t* pMsgQueueLocalMgt = get_msg_queue_local_mgt();
    pPetSmLocalMgt->pSyncInfo->queueCfgFlag = ++pMsgQueueLocalMgt->localSyncInfo.queueCfgFlag;

    return;
}

static inline void msg_transfer_queue_polling(void)
{
    uint8_t port_id = 0;
    HandleId_t handler;
    uint16_t cu_flag;
    uint32_t offset = 0;
    uint32_t len = 0;
    uint8_t* msg_ptr;

    for (uint32_t i = 0; i < MAX_INSTANCE_NUM; i++) {
        handler.port_id = port_id;
        handler.inst_id = i;
        handler.type_id = CU_SPLIT;
        cu_flag = C_PLANE;
        msg_transfer_receive(handler.value, cu_flag, offset, len, &msg_ptr);

        cu_flag = U_PLANE;
        msg_transfer_receive(handler.value, cu_flag, offset, len, &msg_ptr);

        handler.type_id = OAM;
        msg_transfer_receive(handler.value, cu_flag, offset, len, &msg_ptr);
    }

    return;
}

#define CELL_SETUP_TYPE_SIMULATION (0x5a6b7c8d)

void cell_setup_simulation()
{
    uint32_t size = 16;
    char* buf;
    uint32_t availableSize,offset;

    uint16_t cu_flag = C_PLANE;
    HandleId_t handler;
    handler.port_id = 0;
    handler.inst_id = 0;
    handler.type_id = CU_SPLIT;

    //usleep(10000);
    sleep(1);

    int32_t ret = msg_transfer_send_start(handler.value,cu_flag);

    /************C_PLANE***************/
    ret = msg_transfer_alloc_msg(handler.value, cu_flag, size, &buf, &availableSize, &offset);
    if ( SUCCESS != ret) {
        UCP_PRINT_ERROR("cell_setup_simulation call msg_transfer_alloc_msg err.");
        return ;
        //continue;
    }
    
    *(uint32_t*)(buf + 0) = CELL_SETUP_TYPE_SIMULATION;
    *(uint32_t*)(buf + 4) = read_stc_local_timer();

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

    return;
}

int32_t test_case(uint32_t argc, int32_t* argvp)
{
    UCP_PRINT_DEBUG("start running testcase 0.");

    osp_read_spe_cfg_file("/ramfs/cfgDat");

    msg_transfer_mem_init();
    msg_transfer_cfg();
    ucp_handshake();

    UCP_PRINT_DEBUG("start transfering message.");

    uint32_t size = 100;
    char* buf;
    uint32_t availableSize,offset;
    uint8_t* ptr;

    uint16_t cu_flag = C_PLANE;
    HandleId_t handler;
    handler.port_id = 0;
    handler.inst_id = 0;
    handler.type_id = CU_SPLIT;

    int32_t ret;

    cell_setup_simulation();

    while(1) {
        msg_transfer_queue_polling();

        if(1 == slot_ind_flag)
        {
            slot_ind_flag = 0;

            handler.inst_id = 0;

            /************C_PLANE***************/
            cu_flag = C_PLANE;
            ret = msg_transfer_send_start(handler.value,cu_flag);

            ret = msg_transfer_alloc_msg(handler.value, cu_flag, size, &buf, &availableSize, &offset);
            if ( SUCCESS != ret) {
                UCP_PRINT_ERROR("0,c_plane alloc error\r\n");
                continue;
            }

            ptr = (uint8_t *)buf;
            *(uint32_t*)(ptr + 0) = gu32_value;
            *(uint32_t*)(ptr + 4) = gu32_tick_from_tx_ctrl;
            *(uint32_t*)(ptr + 8) = gu32_tick_receive_ctrl;
            *(uint32_t*)(ptr + 12) = read_stc_local_timer();

            ret = msg_transfer_send_msg(handler.value, cu_flag, (uint8_t *)buf, offset, size);
            if ( SUCCESS != ret) {
                UCP_PRINT_ERROR("0,c_plane send error\r\n");
            }

            ret = msg_transfer_send_end(handler.value,cu_flag);

            /************U_PLANE***************/
            cu_flag = U_PLANE;
            ret = msg_transfer_send_start(handler.value,cu_flag);

            ret = msg_transfer_alloc_msg(handler.value, cu_flag, size, &buf, &availableSize, &offset);
            if ( SUCCESS != ret) {
                UCP_PRINT_ERROR("0,u_plane alloc error\r\n");
                continue;
            }

            ptr = (uint8_t *)buf;
            *(uint32_t*)(ptr + 0) = gu32_value;
            *(uint32_t*)(ptr + 4) = gu32_tick_from_tx_ctrl;
            *(uint32_t*)(ptr + 8) = gu32_tick_receive_ctrl;
            *(uint32_t*)(ptr + 12) = read_stc_local_timer();

            ret = msg_transfer_send_msg(handler.value, cu_flag, (uint8_t *)buf, offset, size);
            if ( SUCCESS != ret) {
                UCP_PRINT_ERROR("0,u_plane send error\r\n");
            }

            ret = msg_transfer_send_end(handler.value,cu_flag);

            handler.inst_id = 1;
            /************C_PLANE***************/
            cu_flag = C_PLANE;
            ret = msg_transfer_send_start(handler.value,cu_flag);

            ret = msg_transfer_alloc_msg(handler.value, cu_flag, size, &buf, &availableSize, &offset);
            if ( SUCCESS != ret) {
                UCP_PRINT_ERROR("1,c_plane alloc error\r\n");
                continue;
            }

            ptr = (uint8_t *)buf;
            *(uint32_t*)(ptr + 0) = gu32_value;
            *(uint32_t*)(ptr + 4) = gu32_tick_from_tx_ctrl;
            *(uint32_t*)(ptr + 8) = gu32_tick_receive_ctrl;
            *(uint32_t*)(ptr + 12) = read_stc_local_timer();
            
            ret = msg_transfer_send_msg(handler.value, cu_flag, (uint8_t *)buf, offset, size);
            if ( SUCCESS != ret) {
                UCP_PRINT_ERROR("1,c_plane send error\r\n");
            }

            ret = msg_transfer_send_end(handler.value,cu_flag);

            /************U_PLANE***************/
            cu_flag = U_PLANE;
            ret = msg_transfer_send_start(handler.value,cu_flag);

            ret = msg_transfer_alloc_msg(handler.value, cu_flag, size, &buf, &availableSize, &offset);
            if ( SUCCESS != ret) {
                UCP_PRINT_ERROR("1,u_plane alloc error\r\n");
                continue;
            }

            ptr = (uint8_t *)buf;
            *(uint32_t*)(ptr + 0) = gu32_value;
            *(uint32_t*)(ptr + 4) = gu32_tick_from_tx_ctrl;
            *(uint32_t*)(ptr + 8) = gu32_tick_receive_ctrl;
            *(uint32_t*)(ptr + 12) = read_stc_local_timer();
            
            ret = msg_transfer_send_msg(handler.value, cu_flag, (uint8_t *)buf, offset, size);
            if ( SUCCESS != ret) {
                UCP_PRINT_ERROR("1,u_plane send error\r\n");
            }

            ret = msg_transfer_send_end(handler.value,cu_flag);
        }
    }
    return 0;
}

