// +FHDR------------------------------------------------------------
//                 Copyright (c) 2022 SmartLogic.
//                       ALL RIGHTS RESERVED
// -----------------------------------------------------------------
// Filename      : ospSwQueue.c
// Author        : 
// Created On    : 2023-01-19
// Last Modified :
// -----------------------------------------------------------------
// Description:
//
//
// -FHDR------------------------------------------------------------
#include <stdio.h>
#include <string.h>
#include "ospTypes.h"
#include "ospSwQueue.h"
#include "ospHeap.h"
#include "ucp_printf.h"

#define OSP_APE_RFM_LOG_OFFSET      (0x0AE00000)    /* APE_LOG起始地址为：0xA800 0000 ,Log的实际地址为：0xB2E00000 */
#define OSP_APE_RFM_LOG_SIZE        (0x00080000)    /* Log软件队列一个队列的总内存(512K) */

#define OSP_APE_RFM_SHELL_OFFSET    (0x0B600000)//(0x00800000)
#define OSP_APE_RFM_SHELL_SIZE      (0x00001000)    /* Shell软件队列一个队列的总内存(512*8) */

#define OSP_APE_RFM_QUE_NUM         (36)            /* 一共36个软列队 */

#define OSP_APE_SHARE_OFFSET        (0x0B618000)//(0x00818000)

#define SPU_APE_RFM_QUE_FLAG_USED   (0x5a5a)
#define SPU_APE_FRM_QUE_FLAG_POS    (2)

void *gpsw_que_share_mem  = NULL;
void *gpsw_que_static_mem = NULL;
uint64_t gsw_que_static_mem_size = 0;
spu_sw_queue_mem_t gstsw_queue_mem[OSP_APE_RFM_QUE_NUM];
spu_sw_queue_share_info_t gstsw_queue_share_info[OSP_APE_RFM_QUE_NUM] = {0};

uint8_t osp_sw_queue_mem_init(void)
{
    gsw_que_static_mem_size = 0;

    gpsw_que_static_mem = get_static_mem(APE_LOG, &gsw_que_static_mem_size);
    if (0 == gsw_que_static_mem_size)
    {
        UCP_PRINT_ERROR("[osp_sw_queue_mem_init]: get_static_mem(APE_LOG) return error.");
        return OSP_ERROR;
    }
    gpsw_que_share_mem = gpsw_que_static_mem + OSP_APE_SHARE_OFFSET;
    return OSP_OK;
}

uint8_t osp_sw_queue_init()
{
    uint8_t u8ret  = 0;
    uint8_t u8loop = 0;
    void*   pvlog_addr = NULL;

    memset(&gstsw_queue_mem, 0, sizeof(gstsw_queue_mem));
    memset(&gstsw_queue_share_info, 0, sizeof(gstsw_queue_share_info));

    u8ret = osp_sw_queue_mem_init();
    if (OSP_OK != u8ret)
    {
        UCP_PRINT_ERROR("[osp_sw_queue_init]: osp_sw_queue_mem_init return error.");
        return OSP_ERROR;
    }

    /* 初始化 */
    /* APE_RFM_LOG */
    pvlog_addr = gpsw_que_static_mem + OSP_APE_RFM_LOG_OFFSET;
    for (u8loop = 0; u8loop < OSP_APE_RFM_LOG_NUM; u8loop++)
    {
        gstsw_queue_mem[u8loop].pvaddr         = pvlog_addr + (u8loop*OSP_APE_RFM_LOG_SIZE);
        gstsw_queue_mem[u8loop].u16queue_id    = u8loop;
        gstsw_queue_mem[u8loop].u16queue_type  = OSP_SW_QUEUE_LOG;
        gstsw_queue_mem[u8loop].u8queue_offset = 8;
        gstsw_queue_mem[u8loop].u16queue_dep   = OSP_APE_RFM_MSG_QUE_DEP;
        gstsw_queue_mem[u8loop].u16queue_mask  = (OSP_APE_RFM_MSG_QUE_DEP - 1);
        gstsw_queue_mem[u8loop].u16queue_mem_idx = 0;
        gstsw_queue_mem[u8loop].u32queue_full_count  = 0;
        gstsw_queue_mem[u8loop].u32queue_empty_count = 0;
    }

    /* APE_RFM_SHELL */
    pvlog_addr = gpsw_que_static_mem + OSP_APE_RFM_SHELL_OFFSET;
    for (u8loop = 0; u8loop < OSP_APE_RFM_SHELL_NUM; u8loop++)
    {
        gstsw_queue_mem[u8loop+OSP_APE_RFM_LOG_NUM].pvaddr         = pvlog_addr + (u8loop*OSP_APE_RFM_SHELL_SIZE);
        gstsw_queue_mem[u8loop+OSP_APE_RFM_LOG_NUM].u16queue_id    = (OSP_APE_RFM_LOG_NUM + u8loop);
        gstsw_queue_mem[u8loop+OSP_APE_RFM_LOG_NUM].u16queue_type  = OSP_SW_QUEUE_SHELL;
        gstsw_queue_mem[u8loop+OSP_APE_RFM_LOG_NUM].u8queue_offset = 8;
        gstsw_queue_mem[u8loop+OSP_APE_RFM_LOG_NUM].u16queue_dep   = OSP_APE_RFM_SHELL_QUE_DEP;
        gstsw_queue_mem[u8loop+OSP_APE_RFM_LOG_NUM].u16queue_mask  = (OSP_APE_RFM_SHELL_QUE_DEP - 1);
        gstsw_queue_mem[u8loop+OSP_APE_RFM_LOG_NUM].u16queue_mem_idx = 0;
        gstsw_queue_mem[u8loop+OSP_APE_RFM_LOG_NUM].u32queue_full_count  = 0;
        gstsw_queue_mem[u8loop+OSP_APE_RFM_LOG_NUM].u32queue_empty_count = 0;
    }
    return OSP_OK;
}

int8_t *osp_sw_mem_malloc(osp_sw_queue_index_e emqueue_idx)
{
    uint64_t u64addr = 0;
    u64addr = (uint64_t)((gstsw_queue_mem[emqueue_idx].u16queue_mem_idx << 9) + gstsw_queue_mem[emqueue_idx].pvaddr);
    gstsw_queue_mem[emqueue_idx].u16queue_mem_idx = (gstsw_queue_mem[emqueue_idx].u16queue_mem_idx + 1)&(gstsw_queue_mem[emqueue_idx].u16queue_mask);
    return ((int8_t*)(u64addr + (gstsw_queue_mem[emqueue_idx].u8queue_offset)));
}

uint8_t osp_sw_enque(osp_sw_queue_index_e emqueue_idx, int8_t *pi8addr)
{
    uint16_t u16Size = SPU_SW_QUEUE_SHARE_INFO_SIZE;
    uint16_t u16enque_idx = ((uint64_t)(pi8addr) - (uint64_t)(gstsw_queue_mem[emqueue_idx].pvaddr) - gstsw_queue_mem[emqueue_idx].u8queue_offset)/SPU_APE_RFM_QUE_SIG_SIZE;
    uint16_t u16queue_enque_idx = 0;

    spu_sw_queue_share_info_t *pstsw_queue_share_ture = NULL;
    spu_sw_queue_share_info_t *pstsw_queue_share_base = (spu_sw_queue_share_info_t*)gpsw_que_share_mem;
    pstsw_queue_share_ture = (spu_sw_queue_share_info_t*)((int8_t*)pstsw_queue_share_base + emqueue_idx*u16Size);

    if ((pstsw_queue_share_ture->u16queue_enque_idx - pstsw_queue_share_ture->u16queue_deque_idx) >= gstsw_queue_mem[emqueue_idx].u16queue_dep)
    {
        gstsw_queue_mem[emqueue_idx].u32queue_full_count++;
        UCP_PRINT_LOG("[osp_sw_enque]: queue[%d] is full.", emqueue_idx);
        return 3;
    }

    u16queue_enque_idx = (pstsw_queue_share_ture->u16queue_enque_idx)&(gstsw_queue_mem[emqueue_idx].u16queue_mask);
    pstsw_queue_share_ture->u16queue_msg[u16queue_enque_idx] = u16enque_idx;
    pstsw_queue_share_ture->u16queue_enque_idx = (pstsw_queue_share_ture->u16queue_enque_idx + 1);
    //pstsw_queue_share_ture->u16queue_enque_idx = (pstsw_queue_share_ture->u16queue_enque_idx + 1)&(gstsw_queue_mem[emqueue_idx].u16queue_mask);
    //pstsw_queue_share_ture->u16queue_enque_count++;
    return 0;

}

uint8_t osp_sw_deque(osp_sw_queue_index_e emqueue_idx, osp_sw_msg_info_t **pstmsg_info)
{
    uint16_t u16Size = SPU_SW_QUEUE_SHARE_INFO_SIZE;
    uint16_t u16queue_msg_idx   = 0;
    uint16_t u16queue_deque_idx = 0;

    spu_sw_queue_share_info_t *pstsw_queue_share_ture = NULL;
    spu_sw_queue_share_info_t *pstsw_queue_share_base = (spu_sw_queue_share_info_t*)gpsw_que_share_mem;
    pstsw_queue_share_ture = (spu_sw_queue_share_info_t*)((int8_t*)pstsw_queue_share_base + emqueue_idx*u16Size);

    u16queue_deque_idx = pstsw_queue_share_ture->u16queue_deque_idx&(gstsw_queue_mem[emqueue_idx].u16queue_mask);
    if (pstsw_queue_share_ture->u16queue_deque_idx == pstsw_queue_share_ture->u16queue_enque_idx)
    {
        //UCP_PRINT_ERROR("[osp_sw_deque]: queue[%d] is empty.", emqueue_idx);
        return 4;
    }

    u16queue_msg_idx = pstsw_queue_share_ture->u16queue_msg[u16queue_deque_idx];

    /*printf("[deque]: idx = %d, d_idx = %d, e_idx = %d, addr = %p\r\n", 
        u16queue_msg_idx, 
        //pstsw_queue_share_ture->u16queue_alloc_idx, 
        pstsw_queue_share_ture->u16queue_deque_idx, 
        //pstsw_queue_share_ture->u16queue_deque_count, 
        pstsw_queue_share_ture->u16queue_enque_idx,
        //pstsw_queue_share_ture->u16queue_enque_count,
        gstsw_queue_mem[emqueue_idx].pvaddr);*/

    *pstmsg_info = (osp_sw_msg_info_t*)((gstsw_queue_mem[emqueue_idx].pvaddr) + (u16queue_msg_idx*SPU_APE_RFM_QUE_SIG_SIZE));
    pstsw_queue_share_ture->u16queue_deque_idx = (pstsw_queue_share_ture->u16queue_deque_idx + 1);
    return 0;
}


