/*
 *  Copyright (C) 2020-2024 Texas Instruments Incorporated
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *    Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 *    Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the
 *    distribution.
 *
 *    Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

/**
 *  \file sciserver_tirtos.c
 *
 *  \brief Example Library functions for an application including Sciserver
 *         This file is only for RTOS based applications.
 *
 */

/* ========================================================================== */
/*                             Include Files                                  */
/* ========================================================================== */

#include <stdint.h>
#include <string.h>
#include <strncpy.h>
#include <Platform_Types.h>
#include <ti/csl/csl_types.h>
#include <ti/osal/osal.h>
#include <ti/drv/sciclient/sciserver.h>
#include <ti/drv/sciclient/sciserver_tirtos.h>
#include <sciserver_hwiData.h>
#include "sciserver_secproxyTransfer.h"
#include "Os.h"

/* ========================================================================== */
/*                           Macros & Typedefs                                */
/* ========================================================================== */

/** \brief Macro to determine the size of an array */
#define SCISERVER_ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))

/*Qorix added for compilation need to check */
#define USER_MCU_NAV_HIGH 0
#define USER_MAIN_NAV_HIGH 1
#define USER_MCU_NAV_LOW 2
#define USER_MAIN_NAV_LOW 3

#define BOOT_APP_NUM_STAGES      (3U)
#define BOOT_APP_NAME_MAX_LEN    (16U)

typedef char TCHAR;
typedef void sblEntryPoint_t;


/* ========================================================================== */
/*                            Global Variables                                */
/* ========================================================================== */

HwiP_Handle gSciserverHwiHandles[SCISERVER_HWI_NUM];

/* ========================================================================== */
/*                         Structure Declarations                             */
/* ========================================================================== */

/* None */

/* ========================================================================== */
/*                        Function Declarations                               */
/* ========================================================================== */

/* None */

/* ========================================================================== */
/*                        Internal Function Declarations                      */
/* ========================================================================== */

static int32_t Sciserver_tirtosInitUserTasks(Sciserver_TirtosCfgPrms_t *pPrms);

static sint32 Boot_App(void);

extern int32_t BootApp_mmcBootImageInit(void);
extern int32_t BootApp_mmcsdBootStageImage(sblEntryPoint_t *pEntry, TCHAR *fileName);
extern void BootApp_mmcBootImageDeInit(void);
extern int32_t BootApp_ospiBootStageImage(sblEntryPoint_t *pEntry, uint32_t address);
extern int32_t BootApp_ospiLeaveConfigSPI(bool isNandBootEnabled);
extern void SBL_SPI_init(void);
extern int32_t SBL_ospiInit(void *handle, bool isNandBootEnabled);
extern int32_t SBL_ospiClose(const void *handle);
extern uint8_t gK3xx_evmEntry;
extern TCHAR mmcsd_main_domain_rtos_image_name[BOOT_APP_NUM_STAGES][BOOT_APP_NAME_MAX_LEN];
extern const uint32_t ospi_main_domain_flash_rtos_images[BOOT_APP_NUM_STAGES];

/* ========================================================================== */
/*                          Function Definitions                              */
/* ========================================================================== */

int32_t Sciserver_tirtosInit(Sciserver_TirtosCfgPrms_t *pAppPrms)
{
    Sciserver_CfgPrms_t prms;
    int32_t ret = CSL_PASS;

    if (pAppPrms == NULL)
    {
        ret = CSL_EBADARGS;
    }

    /* Initialize the Init Parameters for the Sciserver */
    if (ret == CSL_PASS)
    {
        ret = Sciserver_initPrms_Init(&prms);
    }
    /* Initialize the Sciserver */
    if (ret == CSL_PASS)
    {
        ret = Sciserver_init(&prms);
    }

    /* user task initialization */
    if (ret == CSL_PASS) {
        ret = Sciserver_tirtosInitUserTasks(pAppPrms);
    }

    /* Set the process State */
    if (ret == CSL_PASS)
    {
        Sciserver_setCtrlState(SCISERVER_PROCESS_STATE_RUN);
    }
    return ret;
}

void Sciserver_tirtosUserMsgHwiFxn(uintptr_t arg)
{
    Sciserver_hwiData *uhd = (Sciserver_hwiData *) arg;
    int32_t ret = CSL_PASS;
    bool soft_error = false;

    Osal_DisableInterrupt(0, uhd->irq_num);

    ret = Sciserver_interruptHandler(uhd, &soft_error);

    if ((ret != CSL_PASS) && (soft_error == true))
    {
        Osal_EnableInterrupt(0, uhd->irq_num);
    }
    else
    {
        if (uhd->semaphore_id == SCISERVER_SEMAPHORE_USER_HI)
        {
            (void)SetEvent(SciServerHighOsTask, SciserverTrigger_UserHi);
        }
        else
        {
            (void)SetEvent(SciServerLowOsTask, SciserverTrigger_UserLo);
        }
    }

    Osal_ClearInterrupt(0, uhd->irq_num);

    if ((ret != CSL_PASS) && (soft_error != true)) {
        /* At this point secure proxy is broken so halt */
        ShutdownOS((StatusType)E_OK);
    }
}

void Sciserver_tirtosUnRegisterIntr(void)
{
    uint32_t i = 0U;

    for (i = 0U; i < SCISERVER_ARRAY_SIZE(sciserver_hwi_list); i++) {
        if (gSciserverHwiHandles[i] != NULL)
        {
            Osal_DeleteInterrupt(gSciserverHwiHandles[i],
                                 sciserver_hwi_list[i].irq_num);
            gSciserverHwiHandles[i] = NULL_PTR;
        }
    }
}

void Sciserver_tirtosDeinit(void)
{
    Sciserver_deinit();
    Sciserver_tirtosUnRegisterIntr();
}

/* ========================================================================== */
/*                 Internal Function Definitions                              */
/* ========================================================================== */

static int32_t Sciserver_tirtosInitUserTasks(Sciserver_TirtosCfgPrms_t *pPrms)
{
    /* Tasks are provided by AUTOSAR OS (SciServerHighOsTask/SciServerLowOsTask). */
    (void)pPrms;
    return CSL_PASS;
}






sint32 SetupSciServer(void)
{
// #if (defined (BUILD_MCU1_0) && (defined (SOC_J721E) || defined (SOC_J7200)))
    Sciserver_TirtosCfgPrms_t appPrms;
    Sciclient_ConfigPrms_t clientPrms;
    sint32 ret = CSL_PASS;
    appPrms.taskPriority[SCISERVER_TASK_USER_LO] = 1;
    appPrms.taskPriority[SCISERVER_TASK_USER_HI] = 4;
    /* Sciclient needs to be initialized before Sciserver. Sciserver depends on
     * Sciclient API to execute message forwarding */
    ret = Sciclient_configPrmsInit(&clientPrms);
    if (ret == CSL_PASS)
    {
    }
        ret = Sciclient_init(&clientPrms);
    if (ret == CSL_PASS)
    {
        ret = Sciserver_tirtosInit(&appPrms);
    }
    if (ret == CSL_PASS)
    {
        // AppUtils_Printf(MSG_NORMAL, "Starting Sciserver..... PASSED\n");
		ret = CSL_PASS;
    }
    else
    {
        // AppUtils_Printf(MSG_NORMAL, "Starting Sciserver..... FAILED\n");
		ret = -1;
    }
// #endif
    return ret;
}


/* user_mcu_nav_high_priority */
ISR(Sciserver_tirtosUserMsgHwiFxn1)
{
    Sciserver_hwiData *uhd =  &sciserver_hwi_list[USER_MCU_NAV_HIGH];
    int32_t ret = CSL_PASS;
    bool soft_error = false;
    /* TI RTOS: Osal_DisableInterrupt(0, (int32_t) uhd->irq_num); */
    *(volatile unsigned int *)(0x40F80000 + 0x400 +
        (CSLR_MCU_R5FSS0_CORE0_INTR_MCU_NAVSS0_INTR_ROUTER_0_OUTL_INTR_6/32)*0x20 + 0x0C) = 0x40;
    ret = Sciserver_interruptHandler(uhd, &soft_error);
    if ((ret != CSL_PASS) && (soft_error == true))
    {
        /* TI RTOS: Osal_EnableInterrupt(0, (int32_t) uhd->irq_num); */
        *(volatile unsigned int *)(0x40F80000 + 0x400 +
            (CSLR_MCU_R5FSS0_CORE0_INTR_MCU_NAVSS0_INTR_ROUTER_0_OUTL_INTR_6/32)*0x20 + 0x08) = 
0x40;
    }
    else
    {
         /* TI RTOS: (void) SemaphoreP_post(gSciserverUserSemHandles[uhd->semaphore_id]); */
        // (void)SetEvent(SciServerHighOsTask,Rte_Ev_Run_CtApSciserverHigh_CtApSciserverHighRunnable_SciserverTrigger_UserHi_Trigger);
        (void)SetEvent(SciServerHighOsTask,SciserverTrigger_UserHi);
    }
    /* TI RTOS: Osal_ClearInterrupt(0, (int32_t) uhd->irq_num); */
    *(volatile unsigned int *)(0x40F80000 + 0x400 +
        (CSLR_MCU_R5FSS0_CORE0_INTR_MCU_NAVSS0_INTR_ROUTER_0_OUTL_INTR_6/32)*0x20 + 0x04) = 0x40;
}


/* user_main_nav_high_priority */
ISR(Sciserver_tirtosUserMsgHwiFxn2)
{
    Sciserver_hwiData *uhd = NULL;
    int32_t ret = CSL_PASS;
    bool soft_error = false;
    uhd =   &sciserver_hwi_list[USER_MAIN_NAV_HIGH];
    /* TI RTOS: Osal_DisableInterrupt(0, (int32_t) uhd->irq_num); */
    *(volatile unsigned int *)(0x40F80000 + 0x400 +
        (CSLR_MCU_R5FSS0_CORE0_INTR_MCU_NAVSS0_INTR_ROUTER_0_OUTL_INTR_7/32)*0x20 + 0x0C) = 0x80;
    ret = Sciserver_interruptHandler(uhd, &soft_error);
    if ((ret != CSL_PASS) && (soft_error == true))
    {
        /* TI RTOS: Osal_EnableInterrupt(0, (int32_t) uhd->irq_num); */
        *(volatile unsigned int *)(0x40F80000 + 0x400 +
            (CSLR_MCU_R5FSS0_CORE0_INTR_MCU_NAVSS0_INTR_ROUTER_0_OUTL_INTR_7/32)*0x20 + 0x08) = 
0x80;
    }
    else
    {
        /* TI RTOS: (void) SemaphoreP_post(gSciserverUserSemHandles[uhd->semaphore_id]); */
        // (void)SetEvent(SciServerHighOsTask,Rte_Ev_Run_CtApSciserverHigh_CtApSciserverHighRunnable_SciserverTrigger_UserHi_Trigger);
        (void)SetEvent(SciServerHighOsTask,SciserverTrigger_UserHi);
    }
    /* TI RTOS: Osal_ClearInterrupt(0, (int32_t) uhd->irq_num); */
    *(volatile unsigned int *)(0x40F80000 + 0x400 +
        (CSLR_MCU_R5FSS0_CORE0_INTR_MCU_NAVSS0_INTR_ROUTER_0_OUTL_INTR_7/32)*0x20 + 0x04) = 0x80;
}

/* user_mcu_nav_low_priority */
ISR(Sciserver_tirtosUserMsgHwiFxn3)
{
    Sciserver_hwiData *uhd =  &sciserver_hwi_list[USER_MCU_NAV_LOW];
    int32_t ret = CSL_PASS;
    bool soft_error = false;
    /* TI RTOS: Osal_DisableInterrupt(0, (int32_t) uhd->irq_num); */
    *(volatile unsigned int *)(0x40F80000 + 0x400 +
        (CSLR_MCU_R5FSS0_CORE0_INTR_MCU_NAVSS0_INTR_ROUTER_0_OUTL_INTR_8/32)*0x20 + 0x0C) = 0x100;
    ret = Sciserver_interruptHandler(uhd, &soft_error);
    if ((ret != CSL_PASS) && (soft_error == true))
    {
        /* TI RTOS: Osal_EnableInterrupt(0, (int32_t) uhd->irq_num); */
        *(volatile unsigned int *)(0x40F80000 + 0x400 +
            (CSLR_MCU_R5FSS0_CORE0_INTR_MCU_NAVSS0_INTR_ROUTER_0_OUTL_INTR_8/32)*0x20 + 0x08) = 
0x100;
    }
    else
    {
        /* TI RTOS: (void) SemaphoreP_post(gSciserverUserSemHandles[uhd->semaphore_id]); */
        // (void)SetEvent(SciServerLowOsTask,Rte_Ev_Run_CtApSciserverLow_CtApSciserverLowRunnable_SciserverTrigger_UserLo_Trigger);
        (void)SetEvent(SciServerLowOsTask,SciserverTrigger_UserLo);
    }
    /* TI RTOS: Osal_ClearInterrupt(0, (int32_t) uhd->irq_num); */
    *(volatile unsigned int *)(0x40F80000 + 0x400 +
        (CSLR_MCU_R5FSS0_CORE0_INTR_MCU_NAVSS0_INTR_ROUTER_0_OUTL_INTR_8/32)*0x20 + 0x04) = 0x100;
}

/* user_main_nav_low_priority */
ISR(Sciserver_tirtosUserMsgHwiFxn4)
{
    Sciserver_hwiData *uhd =  &sciserver_hwi_list[USER_MAIN_NAV_LOW];
    int32_t ret = CSL_PASS;
    bool soft_error = false;
    /* TI RTOS: Osal_DisableInterrupt(0, (int32_t) uhd->irq_num); */
    *(volatile unsigned int *)(0x40F80000 + 0x400 +
        (CSLR_MCU_R5FSS0_CORE0_INTR_MCU_NAVSS0_INTR_ROUTER_0_OUTL_INTR_9/32)*0x20 + 0x0C) = 0x200;
    ret = Sciserver_interruptHandler(uhd, &soft_error);
    if ((ret != CSL_PASS) && (soft_error == true))
    {
        /* TI RTOS: Osal_EnableInterrupt(0, (int32_t) uhd->irq_num); */
        *(volatile unsigned int *)(0x40F80000 + 0x400 +
            (CSLR_MCU_R5FSS0_CORE0_INTR_MCU_NAVSS0_INTR_ROUTER_0_OUTL_INTR_9/32)*0x20 + 0x08) = 
0x200;
    }
    else
    {
        /* TI RTOS: (void) SemaphoreP_post(gSciserverUserSemHandles[uhd->semaphore_id]); */
        // (void)SetEvent(SciServerLowOsTask,Rte_Ev_Run_CtApSciserverLow_CtApSciserverLowRunnable_SciserverTrigger_UserLo_Trigger);
        (void)SetEvent(SciServerLowOsTask,SciserverTrigger_UserLo);
    }
    /* TI RTOS: Osal_ClearInterrupt(0, (int32_t) uhd->irq_num); */
    *(volatile unsigned int *)(0x40F80000 + 0x400 +
        (CSLR_MCU_R5FSS0_CORE0_INTR_MCU_NAVSS0_INTR_ROUTER_0_OUTL_INTR_9/32)*0x20 + 0x04) = 0x200;
}


TASK(BootAppOsTask)
{
    // if (Boot_App() != CSL_PASS)
    // {
        // ShutdownOS((StatusType)E_OK);
    // }
    // else if (SetupSciServer() != CSL_PASS)
    if (SetupSciServer() != CSL_PASS)
    {
        ShutdownOS((StatusType)E_OK);
    }

    (void)TerminateTask();
}



TASK(SciServerHighOsTask)
{
    int32_t ret;
	EventMaskType Event;
 
    while(1)
    {
        WaitEvent(SciserverTrigger_UserHi);
 
        GetEvent(SciServerHighOsTask, &Event);
 
        ClearEvent(SciserverTrigger_UserHi);
 
        GetResource(OsResource_SciserverSync);
 
        // App_Printf("Sciserver Low Task Running\n");

        ret = Sciserver_processtask((Sciserver_taskData *)&gSciserverTaskList[SCISERVER_TASK_USER_HI]);

        ReleaseResource(OsResource_SciserverSync);

        if (ret != CSL_PASS)
        {
            ShutdownOS((StatusType)E_OK);
        }
        else
        {
            Osal_EnableInterrupt(0U, sciserver_hwi_list[(2 * SCISERVER_TASK_USER_HI) +
                    ((int32_t)gSciserverTaskList[SCISERVER_TASK_USER_HI].state->current_buffer_idx)].irq_num);
        }
    }
	 (void)TerminateTask();
}


TASK(SciServerLowOsTask)
{
    int32_t ret;
	EventMaskType Event;
 
    while(1)
    {
        WaitEvent(SciserverTrigger_UserLo);
 
        GetEvent(SciServerLowOsTask, &Event);
 
        ClearEvent(SciserverTrigger_UserLo);
 
        GetResource(OsResource_SciserverSync);
 
        // App_Printf("Sciserver Low Task Running\n");

        ret = Sciserver_processtask((Sciserver_taskData *)&gSciserverTaskList[SCISERVER_TASK_USER_LO]);

        ReleaseResource(OsResource_SciserverSync);

        if (ret != CSL_PASS)
        {
            ShutdownOS((StatusType)E_OK);
        }
        else
        {
            Osal_EnableInterrupt(0U, sciserver_hwi_list[(2 * SCISERVER_TASK_USER_LO) +
                    ((int32_t)gSciserverTaskList[SCISERVER_TASK_USER_LO].state->current_buffer_idx)].irq_num);
        }
    }
	 (void)TerminateTask();
}


/* Main Boot task */
static sint32 Boot_App()
{
    sint32 retVal = (sint32)CSL_EFAIL;
    uint32_t stageIdx;
    sblEntryPoint_t *appEntry = (sblEntryPoint_t *)&gK3xx_evmEntry;
#if defined(BOOT_OSPI)
    void *boardHandle = NULL;
    bool isNandBootEnabled = false;
#endif

#if defined(BOOT_MMCSD) || defined(BOOT_EMMC_UDA)
    retVal = (sint32)BootApp_mmcBootImageInit();
    if (retVal == (sint32)CSL_PASS)
    {
        for (stageIdx = 0U; stageIdx < (uint32_t)BOOT_APP_NUM_STAGES; stageIdx++)
        {
            retVal = (sint32)BootApp_mmcsdBootStageImage(appEntry,
                        mmcsd_main_domain_rtos_image_name[stageIdx]);
            if (retVal != (sint32)CSL_PASS)
            {
                break;
            }
        }

        BootApp_mmcBootImageDeInit();
    }

    /* SD/eMMC test mode: do not mask SD failures with OSPI fallback. */
    return retVal;
#endif

#if defined(BOOT_OSPI)
    SBL_SPI_init();
    retVal = (sint32)SBL_ospiInit(&boardHandle, isNandBootEnabled);
    if (retVal == (sint32)CSL_PASS)
    {
        for (stageIdx = 0U; stageIdx < (uint32_t)BOOT_APP_NUM_STAGES; stageIdx++)
        {
            retVal = (sint32)BootApp_ospiBootStageImage(appEntry,
                        ospi_main_domain_flash_rtos_images[stageIdx]);
            if (retVal != (sint32)CSL_PASS)
            {
                break;
            }
        }
    }

    (void)SBL_ospiClose(&boardHandle);
    (void)BootApp_ospiLeaveConfigSPI(isNandBootEnabled);
#endif

    return retVal;
}