/**********************************************************************************************************************
*  Copyright (C), 2022-2026, SMARTLOGIC TECHNOLOGY LTD.
*  File Name: ecpri_irq.s.c
*  Create Date: 23/09/04
*  Description: eCPRI Interrupt Module Source File
*  Change History: 
*      <author>      <time>      <version>   <desc>
*    1. ShangH      23/09/04        1.0       Build this module
**********************************************************************************************************************/


/* -------------------------------------------------- <INC FILE> --------------------------------------------------- */
#include "ecpri_irq.h"


/* --------------------------------------------------- <VAR DEF> --------------------------------------------------- */
/* eCPRI send flag */
uint32_t g_ecpri_send_flag = 0; /* ECS_RFM0: 0xB7E30100(64) */
/* eCPRI send length */
uint32_t g_ecpri_send_len = 0; /* ECS_RFM0: 0xB7E30104(65) */
/* eCPRI send wait flag */
uint32_t g_ecpri_send_wait_flag = 0; /* ECS_RFM0: 0xB7E30108(66) */

/* eCPRI symbol interrupt interval check flag */
uint32_t g_ecpri_sym_irq_intv_check_flag = 0; /* ECS_RFM0: 0xB7E30110(68) */
/* eCPRI symbol interrupt status check flag */
uint32_t g_ecpri_sym_irq_status_check_flag = 0; /* ECS_RFM0: 0xB7E30114(69) */
/* eCPRI symbol interrupt parameter check flag */
uint32_t g_ecpri_sym_irq_para_check_flag = 0; /* ECS_RFM0: 0xB7E30118(70) */

/* eCPRI symbol interrupt statistic */
EcpriSymIrqStats_t g_ecpri_sym_irq_stats = {0}; /* ECS_RFM0: 0xB7E30140(80) ~ 0xB7E3015C(87) */

/* eCPRI CSU send time statistic */
EcpriTimeStats_t g_ecpri_csu_send_time_stats = {0, 0, 0xFFFFFFFF}; /* ECS_RFM0: 0xB7E30160(88) ~ 0xB7E30168(90) */

/* eCPRI symbol interrupt last cycle */
uint32_t g_ecpri_sym_irq_last_cycle = 0;
/* eCPRI symbol interrupt time statistic */
EcpriTimeStats_t g_ecpri_sym_irq_time_stats = {0, 0, 0xFFFFFFFF}; /* ECS_RFM0: 0xB7E30170(92) ~ 0xB7E30178(94) */

/* eCPRI symbol interrupt status count */
uint32_t g_ecpri_sym_irq_status_cnt = 0; /* ECS_RFM0: 0xB7E30190(100) ~ 0xB7E3031C(199) */

#if (ECPRI_CSU_MODE == ECPRI_CSU_LINK)
/* eCPRI CSU link list address */
uint32_t g_ecpri_csu_list_addr = ECPRI_DBG_ADDR0(256); /* 10G - ECS_RFM0: 0xB7E30400(256) ~ 0xB7E304FC(319) 
                                                          25G - ECS_RFM0: 0xB7E30400(256) ~ 0xB7E305FC(383) */

/* eCPRI CSU node parameter */
stEcpriCsuNodePara *g_ecpri_csu_list_node_ptr = NULL;
#endif


/* -------------------------------------------------- <FUNC DEF> --------------------------------------------------- */
/**********************************************************************************************************************
*  Function: ecpri_sym_irq_init
*  Description: eCPRI symbol interrupt init
*  Input: none
*  Output: none
*  Return: none
*  Others: none
**********************************************************************************************************************/
void ecpri_sym_irq_init(void)
{
    /* eCPRI symbol interrupt statistic info clear */
    memset_ucp((void *)&g_ecpri_sym_irq_stats, 0x00, sizeof(EcpriSymIrqStats_t));
}

/**********************************************************************************************************************
*  Function: ecpri_sym_irq_handle
*  Description: eCPRI symbol interrupt handle
*  Input: 
*    <name>                    <type>                      <desc>
*     slot_id                   uint8_t                     slot index
*     sym_id                    uint8_t                     symbol index
*  Output: none
*  Return: operation result - success or failure.
*  Others: none
**********************************************************************************************************************/
int32_t ecpri_sym_irq_handle(uint8_t slot_id, uint8_t sym_id)
{
#if (ECPRI_CSU_MODE == ECPRI_CSU_REG)
    /* antenna number */
    uint8_t ant_num = ECPRI_10G_ANT_NUM;
    /* antenna index */
    uint8_t ant_id = 0;
#endif
    /* slot type */
    uint8_t slot_type = 0;

    /* start cycle */
    uint32_t start_cycle = 0;
    /* end cycle */
    uint32_t end_cycle = 0;

    g_ecpri_sym_irq_stats.handle_times++;

    /* get eCPRI symbol interrupt interval check flag */
    g_ecpri_sym_irq_intv_check_flag = do_read_volatile((void *)ECPRI_DBG_ADDR0(68)); /* ECS_RFM0: 0xB7E30110(68) */
    if (0 != g_ecpri_sym_irq_intv_check_flag)
    {
        /* eCPRI symbol interrupt interval check */
        ecpri_sym_irq_intv_check();
    }

    /* get eCPRI symbol interrupt status check flag */
    g_ecpri_sym_irq_status_check_flag = do_read_volatile((void *)ECPRI_DBG_ADDR0(69)); /* ECS_RFM0: 0xB7E30114(69) */
    if (0 != g_ecpri_sym_irq_status_check_flag)
    {
        /* eCPRI symbol interrupt status check */
        ecpri_sym_irq_status_check();
    }

    /* get eCPRI send flag */
    g_ecpri_send_flag = do_read_volatile((void *)ECPRI_DBG_ADDR0(64)); /* ECS_RFM0: 0xB7E30100(64) */
    if (0 == g_ecpri_send_flag)
    {
        g_ecpri_sym_irq_stats.handle_succ_times++;

        debug_write(ECPRI_DBG_IDX0(80), g_ecpri_sym_irq_stats.handle_times); /* ECS_RFM0: 0xB7E30140(80) */
        debug_write(ECPRI_DBG_IDX0(81), g_ecpri_sym_irq_stats.handle_succ_times); /* ECS_RFM0: 0xB7E30144(81) */

        return SUCCESS;
    }

    /* get eCPRI symbol interrupt parameter check flag */
    g_ecpri_sym_irq_para_check_flag = do_read_volatile((void *)ECPRI_DBG_ADDR0(70)); /* ECS_RFM0: 0xB7E30118(70) */
    if (0 != g_ecpri_sym_irq_para_check_flag)
    {
        /* input para check */
        if ((ECPRI_SLOT_NUM <= slot_id) || (ECPRI_SYM_NUM <= sym_id))
        {
            g_ecpri_sym_irq_stats.handle_fail_times++;

            debug_write(ECPRI_DBG_IDX0(80), g_ecpri_sym_irq_stats.handle_times); /* ECS_RFM0: 0xB7E30140(80) */
            debug_write(ECPRI_DBG_IDX0(81), g_ecpri_sym_irq_stats.handle_succ_times); /* ECS_RFM0: 0xB7E30144(81) */
            debug_write(ECPRI_DBG_IDX0(82), g_ecpri_sym_irq_stats.handle_fail_times); /* ECS_RFM0: 0xB7E30148(82) */

            debug_write(ECPRI_DBG_IDX0(83), slot_id); /* ECS_RFM0: 0xB7E3014C(83) */
            debug_write(ECPRI_DBG_IDX0(87), sym_id); /* ECS_RFM0: 0xB7E3015C(87) */

            return ERROR;
        }
    }

    /* calculate slot type(odd/even) */
    slot_type = slot_id % ECPRI_SLOT_TYPE;

    /* get end cycle */
    rdmcycle(&start_cycle);

#if (ECPRI_CSU_MODE == ECPRI_CSU_REG)
    /* update antenna number */
    if (ECPRI_OPTION_25G == get_protocol_opt())
    {
        ant_num = ECPRI_25G_ANT_NUM;
    }

    for (ant_id = 0; ant_id < ant_num; ant_id++)
    {
        /* eCPRI symbol interrupt send */
        (void)ecpri_sym_irq_send(ant_id, slot_type, sym_id);
    }
#elif (ECPRI_CSU_MODE == ECPRI_CSU_LINK)
    /* eCPRI symbol interrupt link send */
    ecpri_sym_irq_link_send();
#endif

    /* get start cycle */
    rdmcycle(&end_cycle);

    g_ecpri_csu_send_time_stats.time_cur = (end_cycle + STC_CYCLE_MAX - start_cycle) % STC_CYCLE_MAX + 1;
    debug_write(ECPRI_DBG_IDX0(88), g_ecpri_csu_send_time_stats.time_cur); /* ECS_RFM0: 0xB7E30160(88) */

    if (g_ecpri_csu_send_time_stats.time_max < g_ecpri_csu_send_time_stats.time_cur)
    {
        g_ecpri_csu_send_time_stats.time_max = g_ecpri_csu_send_time_stats.time_cur;
        debug_write(ECPRI_DBG_IDX0(89), g_ecpri_csu_send_time_stats.time_max); /* ECS_RFM0: 0xB7E30164(89) */
    }

    if (g_ecpri_csu_send_time_stats.time_min > g_ecpri_csu_send_time_stats.time_cur)
    {
        g_ecpri_csu_send_time_stats.time_min = g_ecpri_csu_send_time_stats.time_cur;
        debug_write(ECPRI_DBG_IDX0(90), g_ecpri_csu_send_time_stats.time_min); /* ECS_RFM0: 0xB7E30168(90) */
    }

    g_ecpri_sym_irq_stats.handle_succ_times++;

    debug_write(ECPRI_DBG_IDX0(80), g_ecpri_sym_irq_stats.handle_times); /* ECS_RFM0: 0xB7E30140(80) */
    debug_write(ECPRI_DBG_IDX0(81), g_ecpri_sym_irq_stats.handle_succ_times); /* ECS_RFM0: 0xB7E30144(81) */
    debug_write(ECPRI_DBG_IDX0(82), g_ecpri_sym_irq_stats.handle_fail_times); /* ECS_RFM0: 0xB7E30148(82) */

    return SUCCESS;
}

#if (ECPRI_CSU_MODE == ECPRI_CSU_REG)
/**********************************************************************************************************************
*  Function: ecpri_sym_irq_send
*  Description: eCPRI symbol interrupt send
*  Input: 
*    <name>                    <type>                      <desc>
*     ant_id                    uint8_t                     antenna index
*     slot_type                 uint8_t                     slot type
*     sym_id                    uint8_t                     symbol index
*  Output: none
*  Return: operation result - success or failure.
*  Others: none
**********************************************************************************************************************/
int32_t ecpri_sym_irq_send(uint8_t ant_id, uint8_t slot_type, uint8_t sym_id)
{
    /* antenna number */
    uint8_t ant_num = ECPRI_10G_ANT_NUM;
    /* config index */
    uint32_t cfg_id = 0;
    /* packet address */
    uint32_t pkt_addr = 0;
    /* packet length */
    uint32_t pkt_len = 0;

    g_ecpri_sym_irq_stats.send_times++;

    /* update antenna number */
    if (ECPRI_OPTION_25G == get_protocol_opt())
    {
        ant_num = ECPRI_25G_ANT_NUM;
    }

    /* input para check */
    if ((ant_num <= ant_id) || (ECPRI_SLOT_TYPE <= slot_type) || (ECPRI_SYM_NUM <= sym_id))
    {
        g_ecpri_sym_irq_stats.send_fail_times++;

        debug_write(ECPRI_DBG_IDX0(84), g_ecpri_sym_irq_stats.send_times); /* ECS_RFM0: 0xB7E30150(84) */
        debug_write(ECPRI_DBG_IDX0(86), g_ecpri_sym_irq_stats.send_fail_times); /* ECS_RFM0: 0xB7E30158(86) */

        debug_write(ECPRI_DBG_IDX0(96), ant_num); /* ECS_RFM0: 0xB7E30180(96) */
        debug_write(ECPRI_DBG_IDX0(97), ant_id); /* ECS_RFM0: 0xB7E30184(97) */
        debug_write(ECPRI_DBG_IDX0(98), slot_type); /* ECS_RFM0: 0xB7E30188(98) */
        debug_write(ECPRI_DBG_IDX0(99), sym_id); /* ECS_RFM0: 0xB7E3018C(99) */

        return ERROR;
    }

    /* config index */
    cfg_id = ant_id * ECPRI_SLOT_TYPE * ECPRI_SYM_NUM + slot_type * ECPRI_SYM_NUM + sym_id;

    /* get packet address */
    pkt_addr = do_read_volatile((void *)(ECPRI_ANT_BUF_ADDR + cfg_id * ECPRI_SYM_INFO_LEN));

    /* get eCPRI send length */
    g_ecpri_send_len = do_read_volatile((void *)ECPRI_DBG_ADDR0(65)); /* ECS_RFM0: 0xB7E30104(65) */
    if (0 == g_ecpri_send_len)
    {
        /* send real length */
        pkt_len = do_read_volatile((void *)(ECPRI_ANT_BUF_ADDR + cfg_id * ECPRI_SYM_INFO_LEN + sizeof(uint32_t)));
    }
    else
    {
        /* send specify length */
        pkt_len = g_ecpri_send_len;
    }

    /* check config info */
    if ((0 == pkt_addr) || (0 == pkt_len) || (ECPRI_PKT_SIZE < pkt_len))
    {
        g_ecpri_sym_irq_stats.send_fail_times++;

        debug_write(ECPRI_DBG_IDX0(84), g_ecpri_sym_irq_stats.send_times); /* ECS_RFM0: 0xB7E30150(84) */
        debug_write(ECPRI_DBG_IDX0(86), g_ecpri_sym_irq_stats.send_fail_times); /* ECS_RFM0: 0xB7E30158(86) */

        debug_write(ECPRI_DBG_IDX0(91), pkt_addr); /* ECS_RFM0: 0xB7E3016C(91) */
        debug_write(ECPRI_DBG_IDX0(95), pkt_len); /* ECS_RFM0: 0xB7E3017C(95) */

        return ERROR;
    }

    /* get eCPRI send wait flag */
    g_ecpri_send_wait_flag = do_read_volatile((void *)ECPRI_DBG_ADDR0(66)); /* ECS_RFM0: 0xB7E30108(66) */
    if (0 != g_ecpri_send_wait_flag)
    {
        g_ecpri_send_wait_flag = 1;
    }

    /* eCPRI CSU send packet */
    (void)ecpri_csu_send(pkt_addr, pkt_len, (uint8_t)g_ecpri_send_wait_flag);

    g_ecpri_sym_irq_stats.send_succ_times++;

    debug_write(ECPRI_DBG_IDX0(84), g_ecpri_sym_irq_stats.send_times); /* ECS_RFM0: 0xB7E30150(84) */
    debug_write(ECPRI_DBG_IDX0(85), g_ecpri_sym_irq_stats.send_succ_times); /* ECS_RFM0: 0xB7E30154(85) */
    debug_write(ECPRI_DBG_IDX0(86), g_ecpri_sym_irq_stats.send_fail_times); /* ECS_RFM0: 0xB7E30158(86) */

    return SUCCESS;
}
#endif

#if (ECPRI_CSU_MODE == ECPRI_CSU_LINK)
/**********************************************************************************************************************
*  Function: ecpri_sym_irq_link_send
*  Description: eCPRI symbol interrupt link send
*  Input: none
*  Output: none
*  Return: none
*  Others: none
**********************************************************************************************************************/
void ecpri_sym_irq_link_send(void)
{
    /* return value */
    int32_t ret = 0;
    /* antenna number */
    uint8_t ant_num = ECPRI_10G_ANT_NUM;

    g_ecpri_sym_irq_stats.send_times++;

    /* update antenna number */
    if (ECPRI_OPTION_25G == get_protocol_opt())
    {
        ant_num = ECPRI_25G_ANT_NUM;
    }

    /* get eCPRI send wait flag */
    g_ecpri_send_wait_flag = do_read_volatile((void *)ECPRI_DBG_ADDR0(66)); /* ECS_RFM0: 0xB7E30108(66) */
    if (0 != g_ecpri_send_wait_flag)
    {
        g_ecpri_send_wait_flag = 1;
    }

    /* eCPRI CSU link list send */
    ret = ecpri_csu_link_send(g_ecpri_csu_list_addr, ant_num, g_ecpri_csu_list_node_ptr, g_ecpri_send_wait_flag);
    if (ERROR != ret)
    {
        g_ecpri_sym_irq_stats.send_succ_times++;
    }
    else
    {
        g_ecpri_sym_irq_stats.send_fail_times++;
    }

    debug_write(ECPRI_DBG_IDX0(84), g_ecpri_sym_irq_stats.send_times); /* ECS_RFM0: 0xB7E30150(84) */
    debug_write(ECPRI_DBG_IDX0(85), g_ecpri_sym_irq_stats.send_succ_times); /* ECS_RFM0: 0xB7E30154(85) */
    debug_write(ECPRI_DBG_IDX0(86), g_ecpri_sym_irq_stats.send_fail_times); /* ECS_RFM0: 0xB7E30158(86) */
}
#endif

/**********************************************************************************************************************
*  Function: ecpri_sym_irq_intv_check
*  Description: eCPRI symbol interrupt interval check
*  Input: none
*  Output: none
*  Return: none
*  Others: none
**********************************************************************************************************************/
void ecpri_sym_irq_intv_check(void)
{
    /* current cycle */
    uint32_t curr_cycle = 0;

    /* get current cycle */
    rdmcycle(&curr_cycle);

    if (1 == g_ecpri_sym_irq_stats.handle_times)
    {
        g_ecpri_sym_irq_last_cycle = curr_cycle;

        return;
    }

    g_ecpri_sym_irq_time_stats.time_cur = (curr_cycle + STC_CYCLE_MAX - g_ecpri_sym_irq_last_cycle) % STC_CYCLE_MAX + 1;
    debug_write(ECPRI_DBG_IDX0(92), g_ecpri_sym_irq_time_stats.time_cur); /* ECS_RFM0: 0xB7E30170(92) */

    if (g_ecpri_sym_irq_time_stats.time_max < g_ecpri_sym_irq_time_stats.time_cur)
    {
        g_ecpri_sym_irq_time_stats.time_max = g_ecpri_sym_irq_time_stats.time_cur;
        debug_write(ECPRI_DBG_IDX0(93), g_ecpri_sym_irq_time_stats.time_max); /* ECS_RFM0: 0xB7E30174(93) */
    }

    if (g_ecpri_sym_irq_time_stats.time_min > g_ecpri_sym_irq_time_stats.time_cur)
    {
        g_ecpri_sym_irq_time_stats.time_min = g_ecpri_sym_irq_time_stats.time_cur;
        debug_write(ECPRI_DBG_IDX0(94), g_ecpri_sym_irq_time_stats.time_min); /* ECS_RFM0: 0xB7E30178(94) */
    }

    g_ecpri_sym_irq_last_cycle = curr_cycle;
}

/**********************************************************************************************************************
*  Function: ecpri_sym_irq_status_check
*  Description: eCPRI symbol interrupt status check
*  Input: none
*  Output: none
*  Return: none
*  Others: none
**********************************************************************************************************************/
void ecpri_sym_irq_status_check(void)
{
    /* DMA status */
    uint32_t dma_status = 0;

    dma_status = do_read_volatile(&JECS_CSU_DMASTATUS);
    if (0xFFFFFFFF != dma_status)
    {
        g_ecpri_sym_irq_status_cnt++;
        debug_write(ECPRI_DBG_IDX0(100), g_ecpri_sym_irq_status_cnt); /* ECS_RFM0: 0xB7E30190(100) */

        if (100 > g_ecpri_sym_irq_status_cnt)
        {
            debug_write(ECPRI_DBG_IDX0(100 + g_ecpri_sym_irq_status_cnt), dma_status); /* ECS_RFM0: 0xB7E30194(101) ~ 0xB7E3031C(199) */
        }
    }
}



