#include "ucps2-intrin.h"
#include "ucos_ii.h"
#include "os_cpu.h"
#include "smartos.h"
#include "mailbox.h"
#include "sem.h"
#include "inter_vector.h"
#include "timers.h"

#define APEID_ADDR   0x931FFF0

int get_cpuid_times = 0;


typedef unsigned int u32;
typedef int      int32_t;
void ape_init_task(void *arg);
extern int cur_prio;


typedef struct osp_task_data{
    u32 task_id;
    char *task_name;
    u32 task_prio;
    void (*loop_fun)(void *arg);
    u32 task_stack_size;
}sys_info;

typedef struct{
    int task_id;
    int priority;
    char task_name[32];
    char* stack_top;
    char* stack_down;
    int stack_size;
    void (*loop_fun)(void *);
    start_hook_func *user_init_hook;
    int apeid;
}sys_tcb;

char *init_st_ptr = NULL;
int cur_apeid = 0;
int apcid_buf[12] = {0,0,1,1,2,2,3,3,4,4,5,5};


sys_info sys_table[] ={                      \
    {0,"init_task",0,ape_init_task,4096},
    {0xffff,},

};


static void sys_entry(void *arg)
{
    sys_tcb *tcb_val = arg;
    tcb_val->loop_fun(arg);
}


void ape_init_task(void *arg)
{
    sys_tcb *tcb_handle = (sys_tcb *)arg;
    start_hook_func *start_hook = tcb_handle->user_init_hook;
    int tmp_prio = tcb_handle->priority;
    int32_t addr = (int32_t)__ucps2_interrupt5;
    while((*start_hook) != NULL)
    {
        (*start_hook)(tcb_handle->apeid);
        start_hook++;
    }
    timer_init(tcb_handle->apeid);

    __ucps2_IntAddr(addr);
    __ucps2_IntEn(f_Enable);
//  free(tcb_handle->stack_down);
    smart_task_del(tmp_prio);

}

void sys_task_reg(sys_info *task_val,start_hook_func *user_hook,int apeid)
{
    int i = 0;
    sys_tcb *tcb_handle = NULL;
    char *stack_down = NULL;
    char *stack_top = NULL;

    while(task_val->task_id != 0xffff){

        stack_down = malloc(task_val->task_stack_size);
        stack_top = stack_down + task_val->task_stack_size;
        tcb_handle = malloc(sizeof(sys_tcb));
        tcb_handle->task_id = task_val->task_id;
        tcb_handle->priority = task_val->task_prio;
        tcb_handle->stack_size = task_val->task_stack_size;
        tcb_handle->stack_top = stack_top;
        tcb_handle->stack_down = stack_down;
        tcb_handle->loop_fun = task_val->loop_fun;
        tcb_handle->user_init_hook = user_hook;
        tcb_handle->apeid = apeid;
        init_st_ptr = stack_down;
        smart_task_create(sys_entry,
                            tcb_handle,
                            (unsigned int*)stack_top,
                            task_val->task_prio,
                            task_val->task_id,
                            stack_down,
                            task_val->task_stack_size);
        task_val++;
        i++;
    }
}

void smart_kernel_init(start_hook_func *usr_startup,int apeid)
{
    int i;
    OSInit();
#if 0
    enable_interrupt();
    while((*usr_startup) != NULL)
    {
        (*usr_startup)(apeid);
        usr_startup++;
    }
    timer_init(apeid);
#else
    sys_task_reg(sys_table,usr_startup,apeid);

#endif
    OSStart();
}


int smart_get_curprio()
{
    return cur_prio;
}


int smart_get_cpuid()
{
    int apeid;
    if(get_cpuid_times != 0)
    {
        return cur_apeid;
    }
    else
    {
        cur_apeid = *(volatile unsigned int*)APEID_ADDR;
        __ucps2_synch(0);
        get_cpuid_times = 1;
    }
    return cur_apeid;
}

int get_cur_cpuid()
{
    return cur_apeid;

}

int get_apcid()
{
    return apcid_buf[cur_apeid];
}

uint8_t  smart_task_create (void   (*task)(void *p_arg),
                        void    *p_arg,
                        uint32_t  *ptos,
                        uint8_t    prio,
                        uint16_t   id,
                        uint32_t  *pbos,
                        uint32_t   stk_size)
{
    int ret;
    ret = OSTaskCreateExt ((void *)task,
    (void *)p_arg,
    (OS_STK  *)ptos,
    prio,
    id,
    pbos,
    stk_size,
    (void*)0,
     0);
    if(ret == 0)
    {
        return 0;
    }
    return -1;
}


void smart_tick_sleep(int cycle)
{
    OSTimeDly(cycle);
}

int smart_task_del(int prio)
{
    int ret;
    ret = OSTaskDel(prio);
    return ret;
}

int smart_get_ticks()
{
    int ticks;
    OS_ENTER_CRITICAL();
    ticks = OSTime;
    OS_EXIT_CRITICAL();
    return ticks;
}


void smart_int_disable()
{
    ucp_enter_critical();
}


void smart_int_enable()
{
     ucp_exit_critical();
}

int smart_get_reg_prio(int *buf)
{
    int count = 0;
    int i;
    for(i = 1; i < OS_LOWEST_PRIO; i++)
    {
        if(OSTCBPrioTbl[i] != (OS_TCB*)0)
        {
            buf[count] = i;
            count++;
        }
    }
    return count;

}

void smart_reclaim_init_res()
{
    if(init_st_ptr != NULL)
    {
        free(init_st_ptr);
        init_st_ptr = NULL;
    }
}
