/*
    FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
    All rights reserved

    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.

    This file is part of the FreeRTOS distribution and was contributed
    to the project by Technolution B.V. (www.technolution.nl,
    freertos-riscv@technolution.eu) under the terms of the FreeRTOS
    contributors license.

    FreeRTOS is free software; you can redistribute it and/or modify it under
    the terms of the GNU General Public License (version 2) as published by the
    Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.

 ***************************************************************************
    >>!   NOTE: The modification to the GPL is included to allow you to     !<<
    >>!   distribute a combined work that includes FreeRTOS without being   !<<
    >>!   obliged to provide the source code for proprietary components     !<<
    >>!   outside of the FreeRTOS kernel.                                   !<<
 ***************************************************************************

    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    FOR A PARTICULAR PURPOSE.  Full license text is available on the following
    link: http://www.freertos.org/a00114.html

 ***************************************************************************
 *                                                                       *
 *    FreeRTOS provides completely free yet professionally developed,    *
 *    robust, strictly quality controlled, supported, and cross          *
 *    platform software that is more than just the market leader, it     *
 *    is the industry's de facto standard.                               *
 *                                                                       *
 *    Help yourself get started quickly while simultaneously helping     *
 *    to support the FreeRTOS project by purchasing a FreeRTOS           *
 *    tutorial book, reference manual, or both:                          *
 *    http://www.FreeRTOS.org/Documentation                              *
 *                                                                       *
 ***************************************************************************

    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading
    the FAQ page "My application does not run, what could be wrong?".  Have you
    defined configASSERT()?

    http://www.FreeRTOS.org/support - In return for receiving this top quality
    embedded software for free we request you assist our global community by
    participating in the support forum.

    http://www.FreeRTOS.org/training - Investing in training allows your team to
    be as productive as possible as early as possible.  Now you can receive
    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
    Ltd, and the world's leading authority on the world's leading RTOS.

    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
    including FreeRTOS+Trace - an indispensable productivity tool, a DOS
    compatible FAT file system, and our tiny thread aware UDP/IP stack.

    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.

    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS
    licenses offer ticketed support, indemnification and commercial middleware.

    http://www.SafeRTOS.com - High Integrity Systems also provide a safety
    engineered and independently SIL3 certified version for use in safety and
    mission critical applications that require provable dependability.

    1 tab == 4 spaces!
 */

/*
 * main() creates a set of standard demo task and a timer.
 * It then starts the scheduler.  The web documentation provides
 * more details of the standard demo application tasks, which provide no
 * particular functionality, but do provide a good example of how to use the
 * FreeRTOS API.
 *
 *
 * In addition to the standard demo tasks, the following tasks and timer are
 * defined and/or created within this file:
 *
 * "Check" software timer - The check timer period is initially set to three
 * seconds.  Its callback function checks that all the standard demo tasks, and
 * the register check tasks, are not only still executing, but are executing
 * without reporting any errors.
 */

/* Kernel includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "timers.h"

#include "miv_rv32_hal.h"
#include "hw_platform.h"
#include "core_uart_apb.h"
#include "core_gpio.h"
#include "core_timer.h"

#include "task.h"

/* lwIP includes. */
#include "lwip/tcpip.h"
#include "lwip/dhcp.h"
#include "egl_assert.h"
#include "drivers/CoreTSE/core_tse.h"
#include"drivers/CoreSysServices_PF/core_sysservices_pf.h"
#include "ethernet_status.h"
#include "rosa_tosa_i2c.h"
//#include "zl_reg_config.h"
/* Eagle API */
#include "gateway_2port_eth.h"
#include "mss_assert.h"
#include "core_tse.h"
#include "mr_hal.h"
#include "mr_registers.h"
#include "osal.h"
#include "api_init.h"
#include "network_settings.h"
#include "BasicWEB.h"
const char * g_hello_msg = "\n\rWelcome to the OAM";
const char * g_one_gig_msg = "Continuity Check Messages (CCM)  Demo using PolarFire 1G ethernet interface.\n\r";
const char * g_ten_gig_msg = "Continuity Check Messages (CCM)  Demo using PolarFire 10G ethernet interface.\n\r";
const char * g_ten_gig_sfp_msg = "Continuity Check Messages (CCM)  Demo using PolarFire SFP+ 10G ethernet interface.\n\r";


const char * g_configzl_msg = "\n**SPI is up - ZL30364 configuration completed\n\r";
const char * g_carinit_msg = "\n**Carrier PHY, TSE configuration completed\n\r";
const char * g_sysinit_msg = "\n**System TSE configuration completed\n\r";
const char * g_qsuccess_msg = "\n**xRXQueue setup completed\n\r";
const char * g_qfail_msg = "\n**xRXQueue setup failed!\n\r";
const char * g_ddrchk_msg = "\n**DDR W/R test completed\n\r";
const char * g_eglinit_msg = "\n**Eagle assert init completed\n\r";
const char * g_mrhalinit_msg = "\n**Metroam HAL init completed\n\r";
const char * g_macinit_msg = "\n\r**MAC address assignment completed\n\r";
const char * g_lwipinit_msg = "\n**LWIP Stack init completed\n\r";
const char * g_sys_init_start_msg = "\nSystem initialization is in progress...\n\r";
const char * g_sys_init_end_msg = "\nSystem initialization completed.\n\r";

UART_instance_t g_uart;

/*-----------------------------------------------------------------------------
 * GPIO instance data.
 */

gpio_instance_t g_gpio_in;
gpio_instance_t g_gpio_out;

/* Priorities used by the various different tasks. */
#define HTTPD_TASK_PRIORITY                   	1
#define LINK_STATUS_TASK_PRIORITY            	1
#define uartPRIMARY_PRIORITY					1
#define DELAY_VALUE 6000000
#define QUEUE_LENGTH 10


/* The period after which the check timer will expire provided no errors have
been reported by any of the standard demo tasks.  ms are converted to the
equivalent in ticks using the portTICK_PERIOD_MS constant. */
#define mainCHECK_TIMER_PERIOD_MS			( 3000UL / portTICK_PERIOD_MS )

/* A block time of zero simply means "don't block". */
#define mainDONT_BLOCK						( 0UL )

/* Web server task stack size. */
#define HTTPD_STACK_SIZE                        1024
#define LINK_STATUS_TASK_STACK_SIZE             1024


#define ETHERNET_STATUS_QUEUE_LENGTH    1
#define DONT_BLOCK                      0

/*-----------------------------------------------------------*/
void http_server_netconn_thread(void *arg);
void prvLinkRXTask(void * pvParameters);

void prvLinkStatusTask(void * pvParameters);
/*
 * Ethernet interface configuration function.
 */
static void prvEthernetConfigureInterface(void * param);
/*
 * FreeRTOS hook for when malloc fails, enable in FreeRTOSConfig.
 */
void vApplicationMallocFailedHook( void );

/*
 * FreeRTOS hook for when freertos is idling, enable in FreeRTOSConfig.
 */
void vApplicationIdleHook( void );

/*
 * FreeRTOS hook for when a stackoverflow occurs, enable in FreeRTOSConfig.
 */
void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName );
// function with multiple test processes
void startTestProcess(void);

// Bare Metal PHY/TSE Functions
void Phy_advertise(void);
void phy_autonegotiation(void);
void phy_init (void);
void phy_init_temp (void);
void tse_init (void);
void display_output(
        uint8_t* in_buffer,
        uint32_t byte_length
);
void tse_init_sys (void);
void phy_init_sys (void);
void Phy_advertise_sys(void);
void phy_autonegotiation_sys(void);
/*==============================================================================
 *
 */
/* The queue used by PTPd task to trnsmit status information to webserver task. */
xQueueHandle xPTPdOutQueue = NULL;
timer_instance_t g_timer0;
void vMainConfigureTimerForRunTimeStats( void )
{

    const unsigned long ulMax32BitValue = 0xffffffffUL;
#if 0
    MSS_TIM64_init( MSS_TIMER_PERIODIC_MODE );
    MSS_TIM64_load_immediate( ulMax32BitValue, ulMax32BitValue );
    MSS_TIM64_start();
#endif
    TMR_init(&g_timer0,
            CORETIMER0_BASE_ADDR,
            TMR_CONTINUOUS_MODE,
            PRESCALER_DIV_1024,
            ulMax32BitValue);
    TMR_start(&g_timer0);
}

/*-----------------------------------------------------------*/
unsigned long ulGetRunTimeCounterValue( void )
{
    unsigned long long ullCurrentValue = 0u;
#if 0
    const unsigned long long ulMax64BitValue = 0xffffffffffffffffULL;
    unsigned long *pulHighWord, *pulLowWord;

    pulHighWord = ( unsigned long * ) &ullCurrentValue;
    pulLowWord = pulHighWord++;

    MSS_TIM64_get_current_value( ( uint32_t * ) pulHighWord, ( uint32_t * ) pulLowWord );

    //Convert the down count into an upcount.
    ullCurrentValue = ulMax64BitValue - ullCurrentValue;

    //  Scale to a 32bit number of suitable frequency.
    ullCurrentValue >>= 13;
#endif
    ullCurrentValue = TMR_current_value(&g_timer0);
    // Just return 32 bits.
    return ( unsigned long ) ullCurrentValue;
}


/* lwIP MAC configuration. */
static struct netif s_EMAC_if;

/*-----------------------------------------------------------*/

void get_mac_address(uint8_t * mac_addr)
{
    uint32_t inc;

    for(inc = 0; inc < 6; ++inc)
    {
        mac_addr[inc] = s_EMAC_if.hwaddr[inc];
    }
}

uint32_t get_ip_address(void)
{
    return (uint32_t)(s_EMAC_if.ip_addr.addr);
}
extern QueueHandle_t xRXQueue;
#ifdef NR
void ddr_mem_test()
{
    volatile uint32_t *m = (uint32_t *)0x80200000;
    uint32_t i = 0,count=0;
    uint32_t wr,base= 0x12345678,rd;
    UART_init( &g_uart, COREUARTAPB0_BASE_ADDR, BAUD_VALUE_115200, (DATA_8_BITS | NO_PARITY));
    UART_polled_tx_string(&g_uart, (const uint8_t *)"DDR memory testing is in progress\n\r");
    //rd= *(volatile uint32_t *)0x80010000;
    for(i=0;i<1024*256;i++)
    {
        wr= base+i;
        *(m+i)= wr;
        rd = *(m+i);
        if(wr != rd)
        {
            count++;
        }
    }
    if(count==0)
    {
        UART_polled_tx_string(&g_uart, (const uint8_t *)"\n\rDDR3 memory test passed\n\r");
    }
    else
    {
        UART_polled_tx_string(&g_uart, (const uint8_t *)"\n\rDDR3 memory test failed\n\r");
    }
}


void execute_designinfo_service(void)
{
    uint8_t status,data_buffer[128];
    status = SYS_get_design_info(data_buffer, 0);
    if(SYS_SUCCESS == status)
    {

        UART_polled_tx_string(&g_uart, (const uint8_t*)"\r\nDesign Version(MSB first): ");
        //display_output((data_buffer + 33), 1);
        //display_output((data_buffer + 32), 1);
        UART_polled_tx_string(&g_uart,(const uint8_t*)"\r\n");
    }
    else
    {
        UART_polled_tx_string(&g_uart,(const uint8_t*)"DesignInfo Service failed.\r\n");
    }


}
void  GPIO_Init()
{
    GPIO_init(&g_gpio_out, 0x60003000UL, GPIO_APB_32_BITS_BUS);

    /**************************************************************************
     * Configure the GPIOs.
     *************************************************************************/
    GPIO_config( &g_gpio_out, GPIO_0, GPIO_OUTPUT_MODE );

    /**************************************************************************
     * Set the GPIO outputs.
     *************************************************************************/
}
#endif
// VR START Bare Metal PHY/TSE Functions

void delay(uint32_t div)
{
    volatile uint32_t delay_count = 40000000/div ;/// 128u;

    while(delay_count > 0u)
    {
        --delay_count;
    }
}



const uint8_t hex_chars[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
        '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
void display_output
(
        uint8_t* in_buffer,
        uint32_t byte_length
)
{
    uint32_t inc;
    uint8_t byte = 0;

    UART_send(&g_uart, (const uint8_t*)" ", sizeof(" "));
    for(inc = 0; inc < byte_length; ++inc)
    {
        if((inc > 1u) &&(0u == (inc % 16u)))
        {
            UART_send(&g_uart, (const uint8_t*)"\r\n ", sizeof("\r\n "));
        }

        byte = in_buffer[inc];
        UART_send(&g_uart, &hex_chars[(byte & 0x0F)], 1);
        UART_send(&g_uart, &hex_chars[((byte & 0xF0) >> 4) ], 1);

    }

}
void ts_free(void *memPtr)
{
    //osMutexTake(ts_mem_mgnt_mutex,0);
    free(memPtr);
    //vPortFree(memPtr);
}

void * ts_malloc(uint32_t size)
{
    void *memPtr;
    //osMutexTake(ts_mem_mgnt_mutex,0);
    memPtr = malloc(size);
    // memPtr = pvPortMalloc(size);
    //osMutexGive(ts_mem_mgnt_mutex);
    return(memPtr);
}

//VR END Bare Metal PHY/TSE Functions

extern struct netif     g_EMAC_if[PHY_COUNT];
volatile bool           g_init_in_prog;
//VR Implicit global declaration
mrDeviceInfo_t      mrDeviceInfo;


///changed
///
void Phy_advertise(void)
{
    uint32_t phy_reg = 0xFFFF;

    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1C04;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x1;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

    phy_reg = *(volatile unsigned int *) (TSE_BASEADDR + 0x030);
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x0;

    phy_reg &= ~(0x1E);

    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1C04;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x02C) = phy_reg;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1C09;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x1;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

    phy_reg = *(volatile unsigned int *) (TSE_BASEADDR + 0x030);
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x0;

    phy_reg |= 0x200;

    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1C09;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x02C) = phy_reg;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);
}

void phy_autonegotiation(void)
{
    uint32_t phy_reg = 0xFFFF;
    uint16_t autoneg_complete;
    volatile uint32_t copper_aneg_timeout = 1000000u;
    volatile uint32_t sgmii_aneg_timeout = 100000u;
    uint8_t copper_link_up;

    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1C1F;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x02C) = 0x0;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1C00;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x1;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

    phy_reg = *(volatile unsigned int *) (TSE_BASEADDR + 0x030);
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x0;

    phy_reg |= 0x1200;

    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1C00;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x02C) = phy_reg;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

    do {
        *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1C01;
        *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x1;
        while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

        phy_reg = *(volatile unsigned int *) (TSE_BASEADDR + 0x030);
        *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x0;

        autoneg_complete = phy_reg & 0x0020u;
        --copper_aneg_timeout;
    } while(!autoneg_complete && (copper_aneg_timeout != 0u));

    for (volatile uint32_t i = 0; i < 100000; i++);

    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1C01;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x1;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

    phy_reg = *(volatile unsigned int *) (TSE_BASEADDR + 0x030);
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x0;

    copper_link_up = phy_reg & 0x0004;

    if(copper_link_up != 0u)
    {
        *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1200;
        *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x1;
        while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

        phy_reg = *(volatile unsigned int *) (TSE_BASEADDR + 0x030);
        *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x0;

        phy_reg |= 0x1000;

        *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1200;
        *(volatile unsigned int *) (TSE_BASEADDR + 0x02C) = phy_reg;
        while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

        *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1200;
        *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x1;
        while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

        phy_reg = *(volatile unsigned int *) (TSE_BASEADDR + 0x030);
        *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x0;

        phy_reg |= 0x0200;

        *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1200;
        *(volatile unsigned int *) (TSE_BASEADDR + 0x02C) = phy_reg;
        while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

        do {
            *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1201;
            *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x1;
            while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

            phy_reg = *(volatile unsigned int *) (TSE_BASEADDR + 0x030);
            *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x0;


            autoneg_complete = phy_reg & 0x0020;
            --sgmii_aneg_timeout;
        } while((!autoneg_complete) && (sgmii_aneg_timeout != 0u));


    }
}

void phy_init (void)
{
    volatile uint16_t phy_reg_0;
    volatile uint16_t temp;
    volatile uint16_t  id1=0,id2=0,phy_mac_reg = 0;

    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1C02;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x1;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

    id1 = *(volatile unsigned int *) (TSE_BASEADDR + 0x030);
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x0;

    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1C03;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x1;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

    id2 = *(volatile unsigned int *) (TSE_BASEADDR + 0x030);
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x0;

    /* 16E3 bit 7 setting to 1 for SERDES MAC AN EN */
    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1C1F;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x02C) = 0x0003;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1C10;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x1;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

    phy_mac_reg = *(volatile unsigned int *) (TSE_BASEADDR + 0x030);
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x0;

    phy_mac_reg |= 0x80;

    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1C10;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x02C) = phy_mac_reg;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);


    /* Set Register 31 to 0 */
    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1C1F;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x02C) = 0x0010;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);


    phy_mac_reg = 0x80F0;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1C12;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x02C) = phy_mac_reg;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

    while(1)
    {
        *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1C12;
        *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x1;
        while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

        temp = *(volatile unsigned int *) (TSE_BASEADDR + 0x030);
        *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x0;

        if((temp & 0x8000) == 0)
        {
            break;
        }
    }

    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1C1F;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x02C) = 0x0;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1C00;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x1;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

    phy_reg_0 = *(volatile unsigned int *) (TSE_BASEADDR + 0x030);
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x0;

    phy_reg_0 = phy_reg_0 | 0x8000;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1C00;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x02C) = phy_reg_0;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

    while(1)
    {
        *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1C00;
        *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x1;
        while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

        temp = *(volatile unsigned int *) (TSE_BASEADDR + 0x030);
        *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x0;
        if((temp & 0x8000) == 0)
        {
            break;
        }
    }

    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1C00;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x1;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

    temp = *(volatile unsigned int *) (TSE_BASEADDR + 0x030);
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x0;
#if 0 // phy loopback farend

    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1C17;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x1;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

    phy_reg_0 = *(volatile unsigned int *) (TSE_BASEADDR + 0x030);
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x0;

    phy_reg_0 = phy_reg_0 | 0x8;

    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1C17;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x02C) = phy_reg_0;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

#endif
}

void tse_init (void)
{
    uint32_t tse_reg = 0xFFFF, phy_reg;

    //TSE Register settings
    *(volatile unsigned int *) (TSE_BASEADDR + 0x000) = 0x00000005;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x004) = 0x00007203; //0x00007201; without CRC enable
    *(volatile unsigned int *) (TSE_BASEADDR + 0x040) = 0x6060603C;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x044) = 0xB1C00000;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x048) = 0x0000FF00;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x04C) = 0x0FFF0000;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x050) = 0x04000180;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x054) = 0x0680FFFF;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x058) = 0x00000000;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x05C) = 0x0007FFFF;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x1C0) = 0x0000000F;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x020) = 0x0007;

    tse_reg = *(volatile unsigned int *) (TSE_BASEADDR + 0x20);

    phy_init();
    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1200;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x02C) = 0x9000;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1204;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x02C) = 0x0001;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1200;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x02C) = 0x1000;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);


    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1205;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x1;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

    phy_reg = *(volatile unsigned int *) (TSE_BASEADDR + 0x030);
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x0;



    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1200;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x02C) = 0x1200;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x0;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);
}
void phy_init_sys (void)
{
    volatile uint16_t phy_reg_0;
    volatile uint16_t temp;
    volatile uint16_t  id1=0,id2=0,phy_mac_reg = 0;

    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1D02;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x1;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

    id1 = *(volatile unsigned int *) (TSE_BASEADDR + 0x030);
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x0;

    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1D03;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x1;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

    id2 = *(volatile unsigned int *) (TSE_BASEADDR + 0x030);
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x0;

    /* 16E3 bit 7 setting to 1 for SERDES MAC AN EN */
    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1D1F;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x02C) = 0x0003;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1D10;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x1;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

    phy_mac_reg = *(volatile unsigned int *) (TSE_BASEADDR + 0x030);
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x0;

    phy_mac_reg |= 0x80;

    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1D10;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x02C) = phy_mac_reg;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);


    /* Set Register 31 to 0 */
    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1D1F;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x02C) = 0x0010;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);


    phy_mac_reg = 0x80F0;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1D12;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x02C) = phy_mac_reg;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

    while(1)
    {
        *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1D12;
        *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x1;
        while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

        temp = *(volatile unsigned int *) (TSE_BASEADDR + 0x030);
        *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x0;

        if((temp & 0x8000) == 0)
        {
            break;
        }
    }

    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1D1F;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x02C) = 0x0;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1D00;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x1;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

    phy_reg_0 = *(volatile unsigned int *) (TSE_BASEADDR + 0x030);
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x0;

    phy_reg_0 = phy_reg_0 | 0x8000;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1D00;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x02C) = phy_reg_0;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

    while(1)
    {
        *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1D00;
        *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x1;
        while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

        temp = *(volatile unsigned int *) (TSE_BASEADDR + 0x030);
        *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x0;
        if((temp & 0x8000) == 0)
        {
            break;
        }
    }

    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1D00;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x1;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

    temp = *(volatile unsigned int *) (TSE_BASEADDR + 0x030);
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x0;
#if 0 // phy loopback farend

    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1D17;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x1;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

    phy_reg_0 = *(volatile unsigned int *) (TSE_BASEADDR + 0x030);
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x0;

    phy_reg_0 = phy_reg_0 | 0x8;

    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1D17;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x02C) = phy_reg_0;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

#endif
}
void tse_init_sys (void)
{
    uint32_t tse_reg = 0xFFFF, phy_reg;

    //TSE Register settings
    *(volatile unsigned int *) (TSE_BASEADDR_SYS + 0x000) = 0x00000005;
    *(volatile unsigned int *) (TSE_BASEADDR_SYS + 0x004) = 0x00007203; //0x00007201; without CRC enable
    *(volatile unsigned int *) (TSE_BASEADDR_SYS + 0x040) = 0x6060603C;
    *(volatile unsigned int *) (TSE_BASEADDR_SYS + 0x044) = 0xB1C00000;
    *(volatile unsigned int *) (TSE_BASEADDR_SYS + 0x048) = 0x0000FF00;
    *(volatile unsigned int *) (TSE_BASEADDR_SYS + 0x04C) = 0x0FFF0000;
    *(volatile unsigned int *) (TSE_BASEADDR_SYS + 0x050) = 0x04000180;
    *(volatile unsigned int *) (TSE_BASEADDR_SYS + 0x054) = 0x0680FFFF;
    *(volatile unsigned int *) (TSE_BASEADDR_SYS + 0x058) = 0x00000000;
    *(volatile unsigned int *) (TSE_BASEADDR_SYS + 0x05C) = 0x0007FFFF;
    *(volatile unsigned int *) (TSE_BASEADDR_SYS + 0x1C0) = 0x0000000F;
    *(volatile unsigned int *) (TSE_BASEADDR_SYS + 0x020) = 0x0007;

    tse_reg = *(volatile unsigned int *) (TSE_BASEADDR_SYS + 0x20);

    phy_init_sys();
    *(volatile unsigned int *) (TSE_BASEADDR_SYS + 0x028) = 0x1200;
    *(volatile unsigned int *) (TSE_BASEADDR_SYS + 0x02C) = 0x9000;
    while ((*(volatile unsigned int *) (TSE_BASEADDR_SYS + 0x034)) != 0);

    *(volatile unsigned int *) (TSE_BASEADDR_SYS + 0x028) = 0x1204;
    *(volatile unsigned int *) (TSE_BASEADDR_SYS + 0x02C) = 0x0001;
    while ((*(volatile unsigned int *) (TSE_BASEADDR_SYS + 0x034)) != 0);

    *(volatile unsigned int *) (TSE_BASEADDR_SYS + 0x028) = 0x1200;
    *(volatile unsigned int *) (TSE_BASEADDR_SYS + 0x02C) = 0x1000;
    while ((*(volatile unsigned int *) (TSE_BASEADDR_SYS + 0x034)) != 0);


    *(volatile unsigned int *) (TSE_BASEADDR_SYS + 0x028) = 0x1205;
    *(volatile unsigned int *) (TSE_BASEADDR_SYS + 0x024) = 0x1;
    while ((*(volatile unsigned int *) (TSE_BASEADDR_SYS + 0x034)) != 0);

    phy_reg = *(volatile unsigned int *) (TSE_BASEADDR_SYS + 0x030);
    *(volatile unsigned int *) (TSE_BASEADDR_SYS + 0x024) = 0x0;



    *(volatile unsigned int *) (TSE_BASEADDR_SYS + 0x028) = 0x1200;
    *(volatile unsigned int *) (TSE_BASEADDR_SYS + 0x02C) = 0x1200;
    while ((*(volatile unsigned int *) (TSE_BASEADDR_SYS + 0x034)) != 0);

    *(volatile unsigned int *) (TSE_BASEADDR_SYS + 0x024) = 0x0;
    while ((*(volatile unsigned int *) (TSE_BASEADDR_SYS + 0x034)) != 0);
}
#ifdef NR
void phy_init_sys (void)
{
    volatile uint16_t phy_reg_0;
    volatile uint16_t temp;
    volatile uint16_t  id1=0,id2=0,phy_mac_reg = 0;

    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1D02;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x1;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

    id1 = *(volatile unsigned int *) (TSE_BASEADDR + 0x030);
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x0;

    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1D03;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x1;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

    id2 = *(volatile unsigned int *) (TSE_BASEADDR + 0x030);
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x0;

    /* 16E3 bit 7 setting to 1 for SERDES MAC AN EN */
    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1D1F;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x02C) = 0x0003;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1D10;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x1;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

    phy_mac_reg = *(volatile unsigned int *) (TSE_BASEADDR + 0x030);
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x0;

    phy_mac_reg |= 0x80;

    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1D10;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x02C) = phy_mac_reg;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);


    /* Set Register 31 to 0 */
    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1D1F;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x02C) = 0x0010;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);


    phy_mac_reg = 0x80F0;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1D12;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x02C) = phy_mac_reg;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

    while(1)
    {
        *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1D12;
        *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x1;
        while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

        temp = *(volatile unsigned int *) (TSE_BASEADDR + 0x030);
        *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x0;

        if((temp & 0x8000) == 0)
        {
            break;
        }
    }

    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1D1F;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x02C) = 0x0;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1D00;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x1;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

    phy_reg_0 = *(volatile unsigned int *) (TSE_BASEADDR + 0x030);
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x0;

    phy_reg_0 = phy_reg_0 | 0x8000;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1D00;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x02C) = phy_reg_0;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

    while(1)
    {
        *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1D00;
        *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x1;
        while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

        temp = *(volatile unsigned int *) (TSE_BASEADDR + 0x030);
        *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x0;
        if((temp & 0x8000) == 0)
        {
            break;
        }
    }

    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1D00;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x1;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

    temp = *(volatile unsigned int *) (TSE_BASEADDR + 0x030);
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x0;
#if 0 // phy loopback farend

    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1D17;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x1;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

    phy_reg_0 = *(volatile unsigned int *) (TSE_BASEADDR + 0x030);
    *(volatile unsigned int *) (TSE_BASEADDR + 0x024) = 0x0;

    phy_reg_0 = phy_reg_0 | 0x8;

    *(volatile unsigned int *) (TSE_BASEADDR + 0x028) = 0x1D17;
    *(volatile unsigned int *) (TSE_BASEADDR + 0x02C) = phy_reg_0;
    while ((*(volatile unsigned int *) (TSE_BASEADDR + 0x034)) != 0);

#endif
}
#endif
void init_10g_tse_cores()
{
    uint32_t temp_data;

    *(volatile unsigned int *) (TSE_BASEADDR + 0x28C) = 0x1C000; // PADDR[9:6]=0xA, PADDR[5:2] = 0x3, MAC Tx Config Register
    *(volatile unsigned int *) (TSE_BASEADDR + 0x290) = 0x10C;//0x00C;   // PADDR[9:6]=0xA, Offset 0x4, MAC Tx Config Register
    //*(volatile unsigned int *) (TSE_BASEADDR + 0x290) = 0x00C; // PADDR[9:6]=0xA, Offset 0x4, MAC Tx Config Register
    *(volatile unsigned int *) (TSE_BASEADDR + 0x2C0) = 0x0; //0x8; // PADDR[9:6]=0xB, Offset 0x0, MAC Rx Config Register
    *(volatile unsigned int *) (TSE_BASEADDR + 0x2CC) = 0x1C000; // PADDR[9:6]=0xB, offset 0x3, MAC Rx Config Register


    temp_data = *(volatile unsigned int *) (TSE_BASEADDR + 0x28c);
    //display_output(&temp_data,4);
    temp_data = *(volatile unsigned int *) (TSE_BASEADDR + 0x290);
    //display_output(&temp_data,4);
    temp_data = *(volatile unsigned int *) (TSE_BASEADDR + 0x2C0);
    //display_output(&temp_data,4);
    temp_data = *(volatile unsigned int *) (TSE_BASEADDR + 0x2cc);
    //display_output(&temp_data,4);

#ifdef DEBUG_PRINT_L2
    ts_printf("** 10G MAC init completed...**\r\n");
#endif


    // 10G MACCORE_1
#if 0
    UART_send(&g_uart, (const uint8_t *)"\r\n 10G MAC_CORE_1 APB access",
            sizeof("\r\n 10G MAC_CORE_1 APB access"));
    *(volatile unsigned int *) (TSE_BASEADDR_SYS + 0x28C) = 0x1C000; // PADDR[9:6]=0xA, PADDR[5:2] = 0x3, MAC Tx Config Register
    *(volatile unsigned int *) (TSE_BASEADDR_SYS + 0x290) = 0x10C; // PADDR[9:6]=0xA, Offset 0x4, MAC Tx Config Register
    *(volatile unsigned int *) (TSE_BASEADDR_SYS + 0x2C0) = 0x8; // PADDR[9:6]=0xB, Offset 0x0, MAC Rx Config Register
    *(volatile unsigned int *) (TSE_BASEADDR_SYS + 0x2CC) = 0x1C000; // PADDR[9:6]=0xB, offset 0x3, MAC Rx Config Register

    temp_data = *(volatile unsigned int *) (TSE_BASEADDR_SYS + 0x28c);
    display_output(&temp_data,4);
#endif

}



void init_tse_cores()
{
    uint32_t temp_data;
    tse_init();
    temp_data = *(volatile unsigned int *) (TSE_BASEADDR + 0x000);
    // VR display_output(&temp_data,4);
    Phy_advertise();
    phy_autonegotiation();

#ifdef DEBUG_PRINT_L2
    UART_send(&g_uart, (const uint8_t *)"\n**TSE_1 initialization completed\n\r",
            sizeof("\n**TSE_1 initialization completed\n\r"));
#endif
    //  phy_init_sys();
    tse_init_sys();
    temp_data = *(volatile unsigned int *) (TSE_BASEADDR_SYS + 0x000);
    // VR display_output(&temp_data,4);
}

void eth_interface_config(uint32_t *cpuif_metroam_add)
{
    uint8_t user_code[64];

    SYS_init(PF_SYSTEM_SERVICE);
    SYS_get_user_code(user_code,0);
    switch(user_code[0])
    {
    case ONE_GIG:
        UART_polled_tx_string(&g_uart, (const uint8_t *)g_one_gig_msg);
        configure_zl30364(); //1G clock
        init_tse_cores(); //1G
        *cpuif_metroam_add = NID_BASEADDR_1G;
        break;
    case TEN_GIG:
        UART_polled_tx_string(&g_uart, (const uint8_t *)g_ten_gig_msg);
        init_10g_tse_cores(); //10G
        *cpuif_metroam_add = NID_BASEADDR_10G;
        break;
    case TEN_GIG_SFP:
        UART_polled_tx_string(&g_uart, (const uint8_t *)g_ten_gig_sfp_msg);
        config_rosatosa(); //SFP
        break;
    default:
        ;
    }

}

osSemaphore_t       g_print_sem = NULL;
#define UART_TEST 1
int main( void )
{

    networkConfig_t     networkConfig[PHY_COUNT];
    uint32_t cpuif_metroam_add;

    osSemaphoreCreateBinary(g_print_sem);
    ASSERT(g_print_sem != NULL);
    // UART Init and Welcome Message
    UART_init( &g_uart, COREUARTAPB0_BASE_ADDR, BAUD_VALUE_115200, (DATA_8_BITS | NO_PARITY));


#ifdef DEBUG_PRINT_L1
    UART_polled_tx_string(&g_uart, (const uint8_t *)g_hello_msg);
    UART_polled_tx_string(&g_uart, (const uint8_t *)g_sys_init_start_msg);
#endif

    eth_interface_config(&cpuif_metroam_add);

#ifdef DEBUG_PRINT_L2
    //configure_zl30364();
    //UART_polled_tx_string(&g_uart, (const uint8_t *)g_configzl_msg);
#endif






#if 0
    test_mngt();
    while(1)
    {

    }
#endif
    xRXQueue = xQueueCreate( QUEUE_LENGTH, sizeof( uint32_t ) );
    if( xRXQueue == NULL )
    {
        /* Queue was not created and must not be used. */
        UART_polled_tx_string(&g_uart, (const uint8_t *)g_qfail_msg);
    }
    else
    {
#ifdef DEBUG_PRINT_L2
        UART_polled_tx_string(&g_uart, (const uint8_t *)g_qsuccess_msg);
#endif
    }
#if DDR_TEST
    // W/R DDR
    uint8_t match[] = {"\r\n\r\nDDR W/R test: Data Match!\0"};
    uint8_t un_match[] = {"\r\n\r\nDDR W/R test: Data Unmatch!\0"};
    uint32_t *ptr;
    ptr = 0x80010000U;

    for (uint32_t x = 0x0; x < 0xff; x += 1) {
        *ptr =x;
        ptr = ptr + 1;
    }
    ptr = 0x80010000;
    for ( volatile uint32_t data = 0, x = 0; x < 0xff; x +=1, ptr = ptr +1) {
        data = *ptr;
        if (data != x) {
            UART_polled_tx_string(&g_uart, (const uint8_t *)&un_match);
        } else {
            //UART_polled_tx_string(&g_uart, (const uint8_t *)&match);
            //display_output(&data,4);
        }
    }
    UART_polled_tx_string(&g_uart, (const uint8_t *)g_ddrchk_msg);
#endif
    // Initialise Assert so that asserts are logged
    egl_assert_init();
#ifdef DEBUG_PRINT_L2
    UART_polled_tx_string(&g_uart, (const uint8_t *)g_eglinit_msg);
#endif

    // Initialise the MetRoam HAL
    mrHalInit(cpuif_metroam_add);
#ifdef DEBUG_PRINT_L2
    UART_polled_tx_string(&g_uart, (const uint8_t *)g_mrhalinit_msg);
#endif
    // Verify and read the Network Settings
    verifyNvmNetworkSettings(networkConfig);

    // Copy the initial network settings to a global parameter
    mrDeviceInfo.mgntMAC = networkConfig[0].macAddr;
    mrDeviceInfo.wanMAC = networkConfig[1].macAddr;
    mrDeviceInfo.lanMAC = networkConfig[2].macAddr;
    // Initialise the MACs in the fabric and load the receive packet processing task
    gateway_mac_init(mrDeviceInfo.wanMAC,mrDeviceInfo.lanMAC,mrDeviceInfo.mgntMAC,&g_EMAC_if[0]);
#ifdef DEBUG_PRINT_L2
    UART_polled_tx_string(&g_uart, (const uint8_t *)g_macinit_msg);
#endif

    g_init_in_prog = true;
    apiInit();
    g_init_in_prog = false;
    // Start the LWIP Stack
    tcpip_init(configureEthernetInterfaces, (void*)networkConfig);
#ifdef DEBUG_PRINT_L2
    UART_polled_tx_string(&g_uart, (const uint8_t *)g_lwipinit_msg);
#endif
#ifdef DEBUG_PRINT_L1
    UART_polled_tx_string(&g_uart, (const uint8_t *)g_sys_init_end_msg);
#endif
#if ENABLE_NETBIOS
    netbios_init();
    ts_printf("NetBios Enabled\n");
#endif
#if ENABLE_SNTP
    sntp_init();
    ts_printf("SNTP Enabled\n");
#endif
#if NR
    osTaskCreate(vBasicWEBServer,"WEBSVR      ",2048,NULL,OS_STACK_THREAD_PRIO - 1,NULL);
#endif
    /* Create the web server task. */
    //tcpip_init(prvEthernetConfigureInterface, NULL);
    startTestProcess();



#if NR

    uint32_t ram_data;

    mrHalRamWrite(0x12, EXT_SRAM_SEL, 0x12345678);

    mrHalRamRead(0x12, EXT_SRAM_SEL, &ram_data);
    mrHalRamRead(0x12, EXT_SRAM_SEL, &ram_data);
    // ts_printf("EXT_SRAM = %x", ram_data);


#endif

    /* Start the kernel.  From here on, only tasks and interrupts will run. */
#ifdef DEBUG_PRINT_L2
    UART_polled_tx_string(&g_uart, (const uint8_t *)"**Starting vTaskStartScheduler\n\r");
#endif
    //HAL_disable_interrupts();
    HAL_enable_interrupts();
    MRV_enable_local_irq(MRV32_MSYS_EIE0_IRQn );
    vTaskStartScheduler();

    /*
     * If all is well, the scheduler will now be running, and the following line
     * will never be reached.  If the following line does execute, then there
     * was insufficient FreeRTOS heap memory available for the idle and/or timer
     * tasks to be created.  See the memory management section on the FreeRTOS
     * web site for more details.
     */
    /* Exit FreeRTOS */
    return 0;
}
/*-----------------------------------------------------------*/

/*-----------------------------------------------------------*/

void vApplicationMallocFailedHook( void )
{
    /* vApplicationMallocFailedHook() will only be called if
	configUSE_MALLOC_FAILED_HOOK is set to 1 in FreeRTOSConfig.h.  It is a hook
	function that will get called if a call to pvPortMalloc() fails.
	pvPortMalloc() is called internally by the kernel whenever a task, queue,
	timer or semaphore is created.  It is also called by various parts of the
	demo application.  If heap_1.c or heap_2.c are used, then the size of the
	heap available to pvPortMalloc() is defined by configTOTAL_HEAP_SIZE in
	FreeRTOSConfig.h, and the xPortGetFreeHeapSize() API function can be used
	to query the size of free heap space that remains (although it does not
	provide information on how the remaining heap might be fragmented). */
    UART_polled_tx_string(&g_uart, (const uint8_t *)"vApplicationMallocFailedHook\n\r");
    taskDISABLE_INTERRUPTS();
    for( ;; );
}
/*-----------------------------------------------------------*/

void vApplicationIdleHook( void )
{
    volatile size_t xFreeStackSpace;

    /*
     * This function is called on each cycle of the idle task.  In this case it
     * does nothing useful, other than report the amount of FreeRTOS heap that
     * remains unallocated.
     */
    xFreeStackSpace = xPortGetFreeHeapSize();

    if( xFreeStackSpace > 100 )
    {
        /*
         * By now, the kernel has allocated everything it is going to, so if
         * there is a lot of heap remaining unallocated then the value of
         * configTOTAL_HEAP_SIZE in FreeRTOSConfig.h can be reduced accordingly.
         */
    }

}
/*-----------------------------------------------------------*/

void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName )
{
    ( void ) pcTaskName;
    ( void ) pxTask;

    /* Run time stack overflow checking is performed if
	configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2.  This hook
	function is called if a stack overflow is detected. */
    taskDISABLE_INTERRUPTS();
    for( ;; );
}
/*-----------------------------------------------------------*/

static void prvEthernetConfigureInterface(void * param)
{
    struct ip_addr xIpAddr, xNetMast, xGateway;
    extern err_t ethernetif_init( struct netif *netif );

    /* Parameters are not used - suppress compiler error. */
    ( void ) param;

    /* Create and configure the EMAC interface. */
#ifdef NET_USE_DHCP
    IP4_ADDR( &xIpAddr, 0, 0, 0, 0 );
    IP4_ADDR( &xGateway, 192, 168, 1, 254 );
#else
    IP4_ADDR( &xIpAddr, 169, 254, 1, 23 );
    IP4_ADDR( &xGateway, 169, 254, 1, 23 );
#endif

    IP4_ADDR( &xNetMast, 255, 255, 255, 0 );

    netif_add( &s_EMAC_if, &xIpAddr, &xNetMast, &xGateway, NULL, ethernetif_init, tcpip_input );

    /* bring it up */

#ifdef NET_USE_DHCP
    dhcp_start(&s_EMAC_if);
#else
    netif_set_up(&s_EMAC_if);
#endif

    /* make it the default interface */
    netif_set_default(&s_EMAC_if);
}

uint8_t buf[50]={0};
uint32_t ip_addr;
uint16_t address[4];

void prvLinkStatusTask(void * pvParameters)
{
    static uint8_t acquired = 0;

    UART_polled_tx_string(&g_uart, (const uint8_t *)"Acquiring IP address");
    for(;;)
    {
        volatile uint8_t linkup;


        /* Run through loop every 2000 milliseconds. */
        vTaskDelay(2000 / portTICK_RATE_MS);

        if(0 == acquired)
        {
            ip_addr = get_ip_address();
            if(0 != ip_addr)
            {
                acquired = 1;
            }
            UART_polled_tx_string(&g_uart, (const uint8_t *)".");
        }

        if(acquired == 1)
        {

            address[0] = ((uint16_t)((ip_addr >> 24u) & 0x000000FFu));
            address[1] = ((int)((ip_addr >> 16u) & 0x000000FFu));
            address[2] = ((int)((ip_addr >> 8u) & 0x000000FFu));
            address[3] = ((int)((ip_addr ) & 0x000000FFu));

            sprintf(buf, "\n\r %d.%d.%d.%d\n\r",address[3],address[2],address[1],address[0]);

            UART_polled_tx_string(&g_uart, (const uint8_t *)buf);
            vTaskDelay(2000 / portTICK_RATE_MS);
            break;


        }
    }
    vTaskDelete( NULL );
}
void vApplicationTickHook( void )
{

}
