/**
 *   \file  icss_eip.c
 *
 *   \brief  Contains functions specific to Ethernet/IP implementation.
 *   Contains helper functions, half-duplex implementation
 *
 *   Contains function definitions for syntax modification, byte order reversal and DMTimer functions
 *
 *   \date Jun 3, 2013
 *   \author a0131726@ti.com
 *   \copyright (C) Copyright 2013, Texas Instruments, Inc.
 */
#ifndef USE_CPSW_DRIVER
#include "icss_eip_driver.h"
#include "icss_dlr.h"
#include "icss_stormControl.h"

/**External variable containing UART instance number*/
extern unsigned int uartInstance;
extern MAC_CONFIG mac_configuration;

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


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

/**
 * \name eip_driver_init
 * \brief Initialization routine for Ethernet/IP driver functions
 * \param  none
 * \return None
 */
void eip_driver_init(void) {

	/*Add PTP to list of known protocols*/
	addProtocolToList(PTP_PROT_TYPE);

	initStormPreventionTable();

	/*Initialize DLR Engine*/
	initDLR();
}

/**
 * \name eip_driver_start
 * \brief Start DLR and MDIO Timer
 * \param  none
 * \return None
 */
void eip_driver_start(void) {

    enableStormPrevention(HWPORT0);
    enableStormPrevention(HWPORT1);

	/*Start DLR Engine*/
	StartDLR();
}

/**
 * \name eip_driver_stop
 * \brief Stop DLR and MDIO Timer
 * \param  none
 * \return None
 */
void eip_driver_stop(void) {

	disableStormPrevention(HWPORT0);
	disableStormPrevention(HWPORT1);

	/*Halt DLR Engine*/
	StopDLR();
}

/**
 * \name getMACId
 * \brief Get the MAC Id from the network stream, convert it to little endian format and return it
 * assumption MAC is present in big endian byte format and starts from zero offset
 * \param packet byte stream
 * \param MAC pointer to array of six bytes which contain the MAC Id in little endian format
 */
void getMACId(Uint8 *packet, Uint8 *macId) {
	Uint8 *src;
	Uint8 i;
	src = packet;

	//conversion from big endian byte order to little endian byte order
	for(i = 0; i < 6; i++) {
		*(macId + i) = *(src++);
	}
}

/**
 * \name convBigEndianToLittleEndianWord
 * \brief Get a word from the network stream, convert it to little endian format and return it
 * Assumption : word is present in big endian byte format and starts from zero offset
 * \param packet byte stream
 * \return word in little endian format
 */
Uint32 convBigEndianToLittleEndianWord(Uint8 *byte) {
	Uint8 *src;
	Uint32 word = 0;
	src = byte;

	/*conversion from big endian byte order to little endian byte order*/
	word |= *(src++);
	word <<= 8;
	word |= *(src++);
	word <<= 8;
	word |= *(src++);
	word <<= 8;
	word |= *(src++);

	return word;
}

/**
 * \name convBigEndianToLittleEndianHalfWord
 * \brief Get a halfword from the network stream, convert it to little endian format and return it
 * assumption halfword is present in big endian byte format and starts from zero offset
 * \param packet - byte stream
 * \return halfword in little endian format
 */
Uint16 convBigEndianToLittleEndianHalfWord(Uint8 *byte) {
	Uint8 *src;
	Uint32 halfWord = 0;
	src = byte;

	//conversion from big endian byte order to little endian byte order
	halfWord |= *(src++);
	halfWord <<= 8;
	halfWord |= *(src++);

	return halfWord;
}

/**
 * \name DMTimer5ModuleClkConfig
 * \brief Get a halfword from the network stream, convert it to little endian format and return it
 * assumption halfword is present in big endian byte format and starts from zero offset
 * \param none
 * \return none
 */
void DMTimer5ModuleClkConfig(void)
{
    HWREG(SOC_CM_PER_REGS + CM_PER_L3S_CLKSTCTRL) =
                             CM_PER_L3S_CLKSTCTRL_CLKTRCTRL_SW_WKUP;

    while((HWREG(SOC_CM_PER_REGS + CM_PER_L3S_CLKSTCTRL) &
     CM_PER_L3S_CLKSTCTRL_CLKTRCTRL) != CM_PER_L3S_CLKSTCTRL_CLKTRCTRL_SW_WKUP);

    HWREG(SOC_CM_PER_REGS + CM_PER_L3_CLKSTCTRL) =
                             CM_PER_L3_CLKSTCTRL_CLKTRCTRL_SW_WKUP;

    while((HWREG(SOC_CM_PER_REGS + CM_PER_L3_CLKSTCTRL) &
     CM_PER_L3_CLKSTCTRL_CLKTRCTRL) != CM_PER_L3_CLKSTCTRL_CLKTRCTRL_SW_WKUP);

    HWREG(SOC_CM_PER_REGS + CM_PER_L3_INSTR_CLKCTRL) =
                             CM_PER_L3_INSTR_CLKCTRL_MODULEMODE_ENABLE;

    while((HWREG(SOC_CM_PER_REGS + CM_PER_L3_INSTR_CLKCTRL) &
                               CM_PER_L3_INSTR_CLKCTRL_MODULEMODE) !=
                                   CM_PER_L3_INSTR_CLKCTRL_MODULEMODE_ENABLE);

    HWREG(SOC_CM_PER_REGS + CM_PER_L3_CLKCTRL) =
                             CM_PER_L3_CLKCTRL_MODULEMODE_ENABLE;

    while((HWREG(SOC_CM_PER_REGS + CM_PER_L3_CLKCTRL) &
        CM_PER_L3_CLKCTRL_MODULEMODE) != CM_PER_L3_CLKCTRL_MODULEMODE_ENABLE);

    HWREG(SOC_CM_PER_REGS + CM_PER_OCPWP_L3_CLKSTCTRL) =
                             CM_PER_OCPWP_L3_CLKSTCTRL_CLKTRCTRL_SW_WKUP;

    while((HWREG(SOC_CM_PER_REGS + CM_PER_OCPWP_L3_CLKSTCTRL) &
                              CM_PER_OCPWP_L3_CLKSTCTRL_CLKTRCTRL) !=
                                CM_PER_OCPWP_L3_CLKSTCTRL_CLKTRCTRL_SW_WKUP);

    HWREG(SOC_CM_PER_REGS + CM_PER_L4LS_CLKSTCTRL) =
                             CM_PER_L4LS_CLKSTCTRL_CLKTRCTRL_SW_WKUP;

    while((HWREG(SOC_CM_PER_REGS + CM_PER_L4LS_CLKSTCTRL) &
                             CM_PER_L4LS_CLKSTCTRL_CLKTRCTRL) !=
                               CM_PER_L4LS_CLKSTCTRL_CLKTRCTRL_SW_WKUP);

    HWREG(SOC_CM_PER_REGS + CM_PER_L4LS_CLKCTRL) =
                             CM_PER_L4LS_CLKCTRL_MODULEMODE_ENABLE;

    while((HWREG(SOC_CM_PER_REGS + CM_PER_L4LS_CLKCTRL) &
      CM_PER_L4LS_CLKCTRL_MODULEMODE) != CM_PER_L4LS_CLKCTRL_MODULEMODE_ENABLE);

    /* Select the clock source for the Timer2 instance. */
    HWREG(SOC_CM_DPLL_REGS + CM_DPLL_CLKSEL_TIMER5_CLK) &=
          ~(CM_DPLL_CLKSEL_TIMER5_CLK_CLKSEL);

    HWREG(SOC_CM_DPLL_REGS + CM_DPLL_CLKSEL_TIMER5_CLK) |=
          CM_DPLL_CLKSEL_TIMER3_CLK_CLKSEL_CLK_M_OSC;

    while((HWREG(SOC_CM_DPLL_REGS + CM_DPLL_CLKSEL_TIMER5_CLK) &
           CM_DPLL_CLKSEL_TIMER5_CLK_CLKSEL) !=
           CM_DPLL_CLKSEL_TIMER3_CLK_CLKSEL_CLK_M_OSC);

    HWREG(SOC_CM_PER_REGS + CM_PER_TIMER5_CLKCTRL) |=
                             CM_PER_TIMER5_CLKCTRL_MODULEMODE_ENABLE;

    while((HWREG(SOC_CM_PER_REGS + CM_PER_TIMER5_CLKCTRL) &
    CM_PER_TIMER2_CLKCTRL_MODULEMODE) != CM_PER_TIMER5_CLKCTRL_MODULEMODE_ENABLE);

    while(!(HWREG(SOC_CM_PER_REGS + CM_PER_L3S_CLKSTCTRL) &
            CM_PER_L3S_CLKSTCTRL_CLKACTIVITY_L3S_GCLK));

    while(!(HWREG(SOC_CM_PER_REGS + CM_PER_L3_CLKSTCTRL) &
            CM_PER_L3_CLKSTCTRL_CLKACTIVITY_L3_GCLK));

    while(!(HWREG(SOC_CM_PER_REGS + CM_PER_OCPWP_L3_CLKSTCTRL) &
           (CM_PER_OCPWP_L3_CLKSTCTRL_CLKACTIVITY_OCPWP_L3_GCLK |
            CM_PER_OCPWP_L3_CLKSTCTRL_CLKACTIVITY_OCPWP_L4_GCLK)));

    while(!(HWREG(SOC_CM_PER_REGS + CM_PER_L4LS_CLKSTCTRL) &
           (CM_PER_L4LS_CLKSTCTRL_CLKACTIVITY_L4LS_GCLK |
            CM_PER_L4LS_CLKSTCTRL_CLKACTIVITY_TIMER5_GCLK)));

}
#endif
