/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

#include "os/mynewt.h"
#include <hal/hal_bsp.h>
#include <hal/hal_os_tick.h>

#include "os_priv.h"

#include <string.h>

#define OS_TICK_PERIOD ((MYNEWT_VAL(CLOCK_FREQ) / 2) / OS_TICKS_PER_SEC)

extern void SVC_Handler(void);
extern void PendSV_Handler(void);
extern void SysTick_Handler(void);

#if MYNEWT_VAL(HARDFLOAT)
struct ctx_fp {
    uint32_t regs[32];
    uint32_t fcsr;
};
#endif

struct ctx {
    uint32_t regs[30];
    uint32_t epc;
    uint32_t badvaddr;
    uint32_t status;
    uint32_t cause;
#if (__mips_isa_rev < 6)
    uint32_t lo;
    uint32_t hi;
#endif
};

/* XXX: determine how to deal with running un-privileged */
/* only priv currently supported */
uint32_t os_flags = OS_RUN_PRIV;

extern struct os_task g_idle_task;

struct os_task *g_fpu_task;

struct os_task_t* g_fpu_user;

static uint32_t last_compare;

static void timer_handler(void);

/* core timer interrupt */
void __attribute__((interrupt(IPL1AUTO),
vector(_CORE_TIMER_VECTOR))) isr_core_timer(void)
{
    uint32_t compare;

    timer_handler();
    IFS0CLR = _IFS0_CTIF_MASK;
    compare = _CP0_GET_COMPARE();
    do {
        compare += OS_TICK_PERIOD;
        _CP0_SET_COMPARE(compare);
    } while ((int32_t)(compare - _CP0_GET_COUNT()) <= 0);
}

/* context switch interrupt, in ctx.S */
void
__attribute__((interrupt(IPL1AUTO), vector(_CORE_SOFTWARE_0_VECTOR)))
isr_sw0(void);

static void
timer_handler(void)
{
    uint32_t compare = _CP0_GET_COMPARE();
    if (last_compare != compare) {
        os_time_advance((compare - last_compare) / OS_TICK_PERIOD);
        last_compare = compare;
    }
}

void
os_arch_ctx_sw(struct os_task *t)
{
    if ((os_sched_get_current_task() != 0) && (t != 0)) {
        os_sched_ctx_sw_hook(t);
    }

    IFS0SET = _IFS0_CS0IF_MASK;
}

os_sr_t
os_arch_save_sr(void)
{
    os_sr_t sr;
    OS_ENTER_CRITICAL(sr);
    return sr;
}

void
os_arch_restore_sr(os_sr_t isr_ctx)
{
    OS_EXIT_CRITICAL(isr_ctx);
}

int
os_arch_in_critical(void)
{
    return OS_IS_CRITICAL();
}

uint32_t get_global_pointer(void);

static inline int
os_bytes_to_stack_aligned_words(int byts) {
    return (((byts - 1) / OS_STACK_ALIGNMENT) + 1) *
        (OS_STACK_ALIGNMENT/sizeof(os_stack_t));
}

/* assumes stack_top will be 8 aligned */

os_stack_t *
os_arch_task_stack_init(struct os_task *t, os_stack_t *stack_top, int size)
{
    int ctx_space = os_bytes_to_stack_aligned_words(sizeof(struct ctx));
#if MYNEWT_VAL(HARDFLOAT)
    /* If stack does not have space for the FPU context, assume the
    thread won't use it. */
    int lazy_space = os_bytes_to_stack_aligned_words(sizeof(struct ctx_fp));
    if ((lazy_space + ctx_space + 4) >= (size * sizeof(os_stack_t))) {
        /* stack too small */
        stack_top -= 4;
    } else {
        struct ctx_fp ctx_fp;
        ctx_fp.fcsr = 0;
        memcpy(stack_top -
            os_bytes_to_stack_aligned_words(sizeof(struct ctx_fp)),
            &ctx_fp, sizeof(ctx_fp));
        stack_top -= lazy_space + 4;
    }
#else
    stack_top -= 4;
#endif

    os_stack_t *s = stack_top - ctx_space;

    struct ctx ctx;
    ctx.regs[3] = (uint32_t)t->t_arg;
    ctx.regs[27] = get_global_pointer();
    ctx.status = (_CP0_GET_STATUS() & ~_CP0_STATUS_CU1_MASK) | _CP0_STATUS_IE_MASK | _CP0_STATUS_EXL_MASK;
    ctx.cause = _CP0_GET_CAUSE();
    ctx.epc = (uint32_t)t->t_func;
    /* copy struct onto the stack */
    memcpy(s, &ctx, sizeof(ctx));

    return stack_top;
}

void
os_arch_init(void)
{
    os_init_idle_task();
}

os_error_t
os_arch_os_init(void)
{
    os_error_t err;

    err = OS_ERR_IN_ISR;
    if (os_arch_in_isr() == 0) {
        err = OS_OK;
        os_sr_t sr;
        OS_ENTER_CRITICAL(sr);

        _CP0_BIC_STATUS(_CP0_STATUS_IPL_MASK);
        /* multi vector mode */
        INTCONSET = _INTCON_MVEC_MASK;
        /* vector spacing 0x20  */
        _CP0_SET_INTCTL(_CP0_GET_INTCTL() | (1 << _CP0_INTCTL_VS_POSITION));

        /* enable core timer interrupt */
        IEC0SET = _IEC0_CTIE_MASK;
        /* set interrupt priority */
        IPC0CLR = _IPC0_CTIP_MASK;
        IPC0SET = (1 << _IPC0_CTIP_POSITION); /* priority 1 */
        /* set interrupt subpriority */
        IPC0CLR = _IPC0_CTIS_MASK;
        IPC0SET = (0 << _IPC0_CTIS_POSITION); /* subpriority 0 */

        /* enable software interrupt 0 */
        IEC0SET = _IEC0_CS0IE_MASK;
        /* set interrupt priority */
        IPC0CLR = _IPC0_CS0IP_MASK;
        IPC0SET = (1 << _IPC0_CS0IP_POSITION); /* priority 1 */
        /* set interrupt subpriority */
        IPC0CLR = _IPC0_CS0IS_MASK;
        IPC0SET = (0 << _IPC0_CS0IS_POSITION); /* subpriority 0 */

        OS_EXIT_CRITICAL(sr);

        /* should be in kernel mode here */
        os_arch_init();
    }
    return err;
}

uint32_t
os_arch_start(void)
{
    struct os_task *t;

    /* Get the highest priority ready to run to set the current task */
    t = os_sched_next_task();

    /* set the core timer compare register */
    _CP0_SET_COMPARE(_CP0_GET_COUNT() + OS_TICK_PERIOD);

    /* global interrupt enable */
    __builtin_enable_interrupts();

    /* Mark the OS as started, right before we run our first task */
    g_os_started = 1;

    /* Perform context switch to first task */
    os_arch_ctx_sw(t);

    return (uint32_t)(t->t_arg);
}

os_error_t
os_arch_os_start(void)
{
    os_error_t err;

    err = OS_ERR_IN_ISR;
    if (os_arch_in_isr() == 0) {
        err = OS_OK;
        /* should be in kernel mode here */
        os_arch_start();
    }

    return err;
}
