This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

StarterWare "enet_echo" example

Other Parts Discussed in Thread: OMAPL138

Hi,

I use "enet_echo" example to test Ethernet but I don't have PHY into my board. Instead of my emac communicates directly with FPGA.

Can I use this example by doing some modifications? If yes, what are these modifications? It's just to test functionnality of this one.

Is there another example to use without PHY?

Thanks

My board : cpu4 (custom board based to omapl138_lcdk)

  • Hi Sebastien,

    You can't work ETHERNET without PHY.

    /opt/ti/C6748_StarterWare_1_20_04_01/drivers/phy.c

    /opt/ti/C6748_StarterWare_1_20_04_01/drivers/emac.c

    /opt/ti/C6748_StarterWare_1_20_04_01/drivers/emac.c

  • Do you have any solutions?

  • Hi Sebastien,

    Sorry, I don't have idea on this.

    I'm not sure MAC-MAC in OMAPL138.

    You can search our TI E2E forums for this question and check.

    http://e2e.ti.com/support/embedded/linux/f/354/t/234215.aspx

    http://e2e.ti.com/support/arm/sitara_arm/f/791/t/264745.aspx

  • In fact communication has to be done by MII interface with FPGA and without PHY controler.

    You say it's impossible to use an EMAC without PHY. And so I've to develop a PHY controler into FPGA.

    Is it that?

  • Hi Sebastien,

    I'm trying to say is that without external PHY, you can't communicate with ethernet but  In your case FPGA is going to act as PHY.

    Some how PHY is important for ethernet interface.

  • Titus,

    Could you please send me the below files you're refering to, maybe they can help putting MAC is such a state that it doesnt require response from the PHY:

    /opt/ti/C6748_StarterWare_1_20_04_01/drivers/phy.c

    /opt/ti/C6748_StarterWare_1_20_04_01/drivers/emac.c

    /opt/ti/C6748_StarterWare_1_20_04_01/drivers/emac.c

    thanks

  • Hi O'Mellin,

    Please refer to the following links.

    http://software-dl.ti.com/dsps/dsps_public_sw/c6000/starterware/01_20_04_01/index_FDS.html

    http://processors.wiki.ti.com/index.php/StarterWare

    /**
     *  \file   phy.c
     *
     *  \brief  APIs for configuring ethernet PHYs
     *
     *   This file contains the device abstraction APIs for ethernet PHYs.
     */
    
    /*
    * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
    */
    /*
    *  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.
    *
    */
    
    #include "hw_types.h"
    #include "mdio.h"
    #include "phy.h"
    
    #define PHY_ADV_VAL_MASK                 (0x01e0)
    #define PHY_GIG_ADV_VAL_MASK             (0x0300)
    
    /*******************************************************************************
    *                        API FUNCTION DEFINITIONS
    *******************************************************************************/
    /**
     * \brief   Reads the PHY ID.
     *
     * \param   mdioBaseAddr  Base Address of the MDIO Module Registers.
     * \param   phyAddr       PHY Adress.
     *
     * \return  32 bit PHY ID (ID1:ID2)
     *
     **/
    unsigned int PhyIDGet(unsigned int mdioBaseAddr, unsigned int phyAddr)
    {
        unsigned int id = 0;
        unsigned short data;
    
        /* read the ID1 register */
        MDIOPhyRegRead(mdioBaseAddr, phyAddr, PHY_ID1, &data);
    
        /* update the ID1 value */
        id = data << PHY_ID_SHIFT;
     
        /* read the ID2 register */
        MDIOPhyRegRead(mdioBaseAddr, phyAddr, PHY_ID2, &data);
    
        /* update the ID2 value */
        id |= data; 
    
        /* return the ID in ID1:ID2 format */
        return id;
    }
    
    /**
     * \brief   Reads a register from the the PHY
     *
     * \param   mdioBaseAddr  Base Address of the MDIO Module Registers.
     * \param   phyAddr       PHY Adress.
     * \param   regIdx        Index of the register to be read
     * \param   regValAdr     address where value of the register will be written
     *
     * \return  status of the read
     *
     **/
    unsigned int PhyRegRead(unsigned int mdioBaseAddr, unsigned int phyAddr,
                            unsigned int regIdx, unsigned short *regValAdr)
    {
        return (MDIOPhyRegRead(mdioBaseAddr, phyAddr, regIdx, regValAdr));
    }
    
    /**
     * \brief   Writes a register with the input
     *
     * \param   mdioBaseAddr  Base Address of the MDIO Module Registers.
     * \param   phyAddr       PHY Adress.
     * \param   regIdx        Index of the register to be read
     * \param   regValAdr     value to be written
     *
     * \return  None
     *
     **/
    void PhyRegWrite(unsigned int mdioBaseAddr, unsigned int phyAddr,
                     unsigned int regIdx, unsigned short regVal)
    {
        MDIOPhyRegWrite(mdioBaseAddr, phyAddr, regIdx, regVal);
    }
    
    /**
     * \brief   Enables Loop Back mode
     *
     * \param   mdioBaseAddr  Base Address of the MDIO Module Registers.
     * \param   phyAddr       PHY Adress.
     *
     * \return  status after enabling.  \n
     *          TRUE if loop back is enabled \n
     *          FALSE if not able to enable
     *
     **/
    unsigned int PhyLoopBackEnable(unsigned int mdioBaseAddr, unsigned int phyAddr)
    {
        unsigned short data;
    
        if(MDIOPhyRegRead(mdioBaseAddr, phyAddr, PHY_BCR, &data) != TRUE )
        {
            return FALSE;
        }
    
        data |= PHY_LPBK_ENABLE;
    
        /* Enable loop back */
        MDIOPhyRegWrite(mdioBaseAddr, phyAddr, PHY_BCR, data);
    
        return TRUE;
    }
    
    /**
     * \brief   Disables Loop Back mode
     *
     * \param   mdioBaseAddr  Base Address of the MDIO Module Registers.
     * \param   phyAddr       PHY Adress.
     *
     * \return  status after enabling.  \n
     *          TRUE if loop back is disabled \n
     *          FALSE if not able to disable
     *
     **/
    unsigned int PhyLoopBackDisable(unsigned int mdioBaseAddr, unsigned int phyAddr)
    {
        unsigned short data;
    
        if(MDIOPhyRegRead(mdioBaseAddr, phyAddr, PHY_BCR, &data) != TRUE )
        {
            return FALSE;
        }
    
        data &= ~(PHY_LPBK_ENABLE);
    
        /* Disable loop back */
        MDIOPhyRegWrite(mdioBaseAddr, phyAddr, PHY_BCR, data);
    
        return TRUE;
    }
    
    /**
     * \brief   Resets the PHY
     *
     * \param   mdioBaseAddr  Base Address of the MDIO Module Registers.
     * \param   phyAddr       PHY Adress.
     * \param   speed         Speed to be enabled
     * \param   duplexMode    Duplex Mode
     *
     * \return  status after configuring \n
     *          TRUE if configuration successful
     *          FALSE if configuration failed
     *
     **/
    unsigned int PhyReset(unsigned int mdioBaseAddr, unsigned int phyAddr)
    {
        unsigned short data;
    
        data = PHY_SOFTRESET;
    
        /* Reset the phy */
        MDIOPhyRegWrite(mdioBaseAddr, phyAddr, PHY_BCR, data);
    
        /* wait till the reset bit is auto cleared */
        while(data & PHY_SOFTRESET)
        {
            /* Read the reset */
            if(MDIOPhyRegRead(mdioBaseAddr, phyAddr, PHY_BCR, &data) != TRUE)
            {
                return FALSE;
            }
        }
    
        return TRUE;
    }
    
    /**
     * \brief   Configures the PHY for a given speed and duplex mode.
     *
     * \param   mdioBaseAddr  Base Address of the MDIO Module Registers.
     * \param   phyAddr       PHY Adress.
     * \param   speed         Speed to be enabled
     * \param   duplexMode    Duplex Mode
     *
     * \return  status after configuring \n
     *          TRUE if configuration successful
     *          FALSE if configuration failed
     *
     **/
    unsigned int PhyConfigure(unsigned int mdioBaseAddr, unsigned int phyAddr,
                              unsigned short speed, unsigned short duplexMode)
    {
        /* Set the configurations */
        MDIOPhyRegWrite(mdioBaseAddr, phyAddr, PHY_BCR, (speed | duplexMode));
    
        return TRUE;
    }
    
    /**
     * \brief   This function ask the phy device to start auto negotiation.
     *          
     *
     * \param   mdioBaseAddr  Base Address of the MDIO Module Registers.
     * \param   phyAddr       PHY Adress.
     * \param   advVal        Autonegotiation advertisement value
     * \param   gigAdvVal     Gigabit capability advertisement value
     *          advVal can take the following any OR combination of the values \n
     *               PHY_100BTX - 100BaseTX \n
     *               PHY_100BTX_FD - Full duplex capabilty for 100BaseTX \n
     *               PHY_10BT - 10BaseT \n
     *               PHY_10BT_FD - Full duplex capability for 10BaseT \n
     *          gigAdvVal can take one of the following values \n
     *               PHY_NO_1000BT - No 1000Base-T capability\n
     *               PHY_1000BT_FD - Full duplex capabilty for 1000 Base-T \n
     *               PHY_1000BT_HD - Half duplex capabilty for 1000 Base-T \n
     *               FALSE - It is passed as an argument if phy dosen't support
     *                       Giga bit capability 
     *
     * \return  status after autonegotiation \n
     *          TRUE if autonegotiation started
     *          FALSE if autonegotiation not started
     *
     **/
    unsigned int PhyAutoNegotiate(unsigned int mdioBaseAddr, unsigned int phyAddr,
                                  unsigned short *advPtr, unsigned short *gigAdvPtr)
    {
        volatile unsigned short data;
        volatile unsigned short anar;
    
        if(MDIOPhyRegRead(mdioBaseAddr, phyAddr, PHY_BCR, &data) != TRUE )
        {
            return FALSE;
        }
       
        data |= PHY_AUTONEG_ENABLE;
    
        if (*gigAdvPtr != 0)
        {
            /* Set phy for gigabit speed */
            data &= PHY_SPEED_MASK;
            data |= PHY_SPEED_1000MBPS;
        }
       
        /* Enable Auto Negotiation */
        MDIOPhyRegWrite(mdioBaseAddr, phyAddr, PHY_BCR, data);
    
        if(MDIOPhyRegRead(mdioBaseAddr, phyAddr, PHY_BCR, &data) != TRUE )
        {
            return FALSE;
        }
    
        /* Write Auto Negotiation capabilities */
        MDIOPhyRegRead(mdioBaseAddr, phyAddr, PHY_AUTONEG_ADV, &anar);
        anar &= ~PHY_ADV_VAL_MASK;
        MDIOPhyRegWrite(mdioBaseAddr, phyAddr, PHY_AUTONEG_ADV, (anar |(*advPtr)));
    
        /* Write Auto Negotiation Gigabyte capabilities */
        anar = 0;
        MDIOPhyRegRead(mdioBaseAddr, phyAddr, PHY_1000BT_CONTROL, &anar);
        anar &= ~PHY_GIG_ADV_VAL_MASK;
        MDIOPhyRegWrite(mdioBaseAddr, phyAddr, PHY_1000BT_CONTROL,
                        (anar |(*gigAdvPtr)));
    
        data |= PHY_AUTONEG_RESTART;
    
        /* Start Auto Negotiation */
        MDIOPhyRegWrite(mdioBaseAddr, phyAddr, PHY_BCR, data);
    
        return TRUE;
    }
    
    /**
     * \brief   Returns the status of Auto Negotiation completion.
     *
     * \param   mdioBaseAddr  Base Address of the MDIO Module Registers.
     * \param   phyAddr       PHY Adress.
     *
     * \return  Auto negotiation completion status \n
     *          TRUE if auto negotiation is completed
     *          FALSE if auto negotiation is not completed
     **/
    unsigned int PhyAutoNegStatusGet(unsigned int mdioBaseAddr, unsigned int phyAddr)
    {
        volatile unsigned short data;
    
        MDIOPhyRegRead(mdioBaseAddr, phyAddr, PHY_BSR, &data);
    
        /* Auto negotiation completion status */
        if(PHY_AUTONEG_COMPLETE == (data & (PHY_AUTONEG_STATUS)))
        {
            return TRUE;
        }
      
        return FALSE;
    }
    
    /**
     * \brief   Reads the Link Partner Ability register of the PHY.
     *
     * \param   mdioBaseAddr    Base Address of the MDIO Module Registers.
     * \param   phyAddr         PHY Adress.
     * \param   ptnerAblty      Pointer to which partner ability will be written.
     * \param   gbpsPtnerAblty  Pointer to which Giga bit capability will be written.
     *
     *          gbpsPtnerAblty can take following Macros.\n
     *
     *          TRUE  - It is passed as argument if phy supports Giga bit capability.\n
     *          FALSE - It is passed as argument if phy dosen't supports Giga bit
     *                  capability.\n
     *
     * \return  status after reading \n
     *          TRUE if reading successful
     *          FALSE if reading failed
     **/
    unsigned int PhyPartnerAbilityGet(unsigned int mdioBaseAddr, 
                                      unsigned int phyAddr,
                                      unsigned short *ptnerAblty,
                                      unsigned short *gbpsPtnerAblty)
    {
        unsigned int status;
    
        status = MDIOPhyRegRead(mdioBaseAddr, phyAddr, PHY_LINK_PARTNER_ABLTY,
                               ptnerAblty);
    
        if (*gbpsPtnerAblty != 0)
        {
            status = status | MDIOPhyRegRead(mdioBaseAddr, phyAddr, PHY_1000BT_STATUS,
                                             gbpsPtnerAblty);
        }
    
        return status;
    }
    
    /**
     * \brief   Reads the link status of the PHY.
     *
     * \param   mdioBaseAddr  Base Address of the MDIO Module Registers.
     * \param   phyAddr       PHY Adress.
     * \param   retries       The number of retries before indicating down status
     *
     * \return  link status after reading \n
     *          TRUE if link is up
     *          FALSE if link is down \n
     *
     * \note    This reads both the basic status register of the PHY and the
     *          link register of MDIO for double check
     **/
    unsigned int PhyLinkStatusGet(unsigned int mdioBaseAddr,
                                  unsigned int phyAddr,
                                  volatile unsigned int retries)
    {
        volatile unsigned short linkStatus;
     
        retries++;   
        while (retries)
        {
            /* First read the BSR of the PHY */
            MDIOPhyRegRead(mdioBaseAddr, phyAddr, PHY_BSR, &linkStatus);
    
            if(linkStatus & PHY_LINK_STATUS)
            {
                return TRUE;
            }
       
            retries--;
        }
    
        return FALSE;
    }
    
    /**************************** End Of File ***********************************/
    

    /**
     *  \file   emac.c
     *
     *  \brief  EMAC APIs.
     *
     *   This file contains the device abstraction layer APIs for EMAC.
     */
    
    /*
    * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
    */
    /*
    *  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.
    *
    */
    
    /* HW Macros and Peripheral Defines */
    #include "hw_types.h"
    #include "hw_emac.h"
    #include "hw_emac_ctrl.h"
    
    /* Driver APIs */
    #include "emac.h"
    
    /*******************************************************************************
    *                       INTERNAL MACRO DEFINITIONS
    *******************************************************************************/
    #define EMAC_CONTROL_RESET             (0x01u)
    #define EMAC_SOFT_RESET                (0x01u)
    #define EMAC_MAX_HEADER_DESC           (8u)
    #define EMAC_UNICAST_DISABLE           (0xFFu)
    
    /*******************************************************************************
    *                        API FUNCTION DEFINITIONS
    *******************************************************************************/
    /**
     * \brief   Enables the TXPULSE Interrupt Generation.
     *
     * \param   emacBase      Base address of the EMAC Module registers.
     * \param   emacCtrlBase  Base address of the EMAC CONTROL module registers
     * \param   ctrlCore      Control core for which the interrupt to be enabled.
     * \param   channel       Channel number for which interrupt to be enabled
     *
     * \return  None
     *
     **/
    void EMACTxIntPulseEnable(unsigned int emacBase, unsigned int emacCtrlBase,
                              unsigned int ctrlCore, unsigned int channel)
    {
        HWREG(emacBase + EMAC_TXINTMASKSET) |= (1 << channel);
    
        HWREG(emacCtrlBase + EMAC_CTRL_CnTXEN(ctrlCore)) |= (1 << channel);
    }
    
    /**
     * \brief   Disables the TXPULSE Interrupt Generation.
     *
     * \param   emacBase      Base address of the EMAC Module registers.
     * \param   emacCtrlBase  Base address of the EMAC CONTROL module registers
     * \param   ctrlCore      Control core for which the interrupt to be disabled.
     * \param   channel       Channel number for which interrupt to be disabled
     *
     * \return  None
     *
     **/
    void EMACTxIntPulseDisable(unsigned int emacBase, unsigned int emacCtrlBase,
                               unsigned int ctrlCore, unsigned int channel)
    {
        HWREG(emacBase + EMAC_TXINTMASKCLEAR) |= (1 << channel);
    
        HWREG(emacCtrlBase + EMAC_CTRL_CnTXEN(ctrlCore)) &= ~(1 << channel);
    }
    
    /**
     * \brief   Enables the RXPULSE Interrupt Generation.
     *
     * \param   emacBase      Base address of the EMAC Module registers.
     * \param   emacCtrlBase  Base address of the EMAC CONTROL module registers
     * \param   ctrlCore      Control core for which the interrupt to be enabled.
     * \param   channel       Channel number for which interrupt to be enabled
     *
     * \return  None
     *
     **/
    void EMACRxIntPulseEnable(unsigned int emacBase, unsigned int emacCtrlBase,
                              unsigned int ctrlCore, unsigned int channel)
    {
        HWREG(emacBase + EMAC_RXINTMASKSET) |= (1 << channel);
    
        HWREG(emacCtrlBase + EMAC_CTRL_CnRXEN(ctrlCore)) |= (1 << channel);
    }
    
    /**
     * \brief   Disables the RXPULSE Interrupt Generation.
     *
     * \param   emacBase      Base address of the EMAC Module registers.
     * \param   emacCtrlBase  Base address of the EMAC CONTROL module registers
     * \param   ctrlCore      Control core for which the interrupt to be disabled.
     * \param   channel       Channel number for which interrupt to be disabled
     *
     * \return  None
     *
     **/
    void EMACRxIntPulseDisable(unsigned int emacBase, unsigned int emacCtrlBase,
                               unsigned int ctrlCore, unsigned int channel)
    {
        HWREG(emacBase + EMAC_RXINTMASKCLEAR) |= (1 << channel);
    
        HWREG(emacCtrlBase + EMAC_CTRL_CnRXEN(ctrlCore)) &= ~(1 << channel);
    }
    /**
     * \brief   This API sets the RMII speed. The RMII Speed can be 10 Mbps or 
     *          100 Mbps
     *
     * \param   emacBase     Base address of the EMAC Module registers.
     * \param   speed        speed for setting.
     *          speed can take the following values. \n
     *                EMAC_RMIISPEED_10MBPS - 10 Mbps \n
     *                EMAC_RMIISPEED_100MBPS - 100 Mbps. 
     *
     * \return  None
     *
     **/
    void EMACRMIISpeedSet(unsigned int emacBase, unsigned int speed)
    {
        HWREG(emacBase + EMAC_MACCONTROL) &= ~EMAC_MACCONTROL_RMIISPEED;
        
        HWREG(emacBase + EMAC_MACCONTROL) |= speed;
    }
    
    /**
     * \brief   This API enables the MII control block
     *
     * \param   emacBase     Base address of the EMAC Module registers.
     *
     * \return  None
     *
     **/
    void EMACMIIEnable(unsigned int emacBase)
    {
        HWREG(emacBase + EMAC_MACCONTROL) |= EMAC_MACCONTROL_GMIIEN;
    }
    
    /**
     * \brief   This API sets the duplex mode of operation(full/half) for MAC.
     *
     * \param   emacBase     Base address of the EMAC Module registers.
     * \param   duplexMode   duplex mode of operation.
     *          duplexMode can take the following values. \n
     *                EMAC_DUPLEX_FULL - Full Duplex  \n
     *                EMAC_DUPLEX_HALF - Half Duplex.
     *
     * \return  None
     *
     **/
    void EMACDuplexSet(unsigned int emacBase, unsigned int duplexMode)
    {
        HWREG(emacBase + EMAC_MACCONTROL) &= ~EMAC_MACCONTROL_FULLDUPLEX;
        
        HWREG(emacBase + EMAC_MACCONTROL) |= duplexMode;
    }
    
    /**
     * \brief   API to enable the transmit in the TX Control Register
     *          After the transmit is enabled, any write to TXHDP of
     *          a channel will start transmission
     *
     * \param   emacBase      Base Address of the EMAC Module Registers.
     *
     * \return  None
     *
     **/
    void EMACTxEnable(unsigned int emacBase)
    {
        HWREG(emacBase + EMAC_TXCONTROL) = EMAC_TXCONTROL_TXEN;
    }
    
    /**
     * \brief   API to enable the receive in the RX Control Register
     *          After the transmit is enabled, and write to RXHDP of
     *          a channel, the data can be received in the destination
     *          specified by the corresponding RX buffer descriptor.
     *
     * \param   emacBase      Base Address of the EMAC Module Registers.
     *
     * \return  None
     *
     **/
    void EMACRxEnable(unsigned int emacBase)
    {
        HWREG(emacBase + EMAC_RXCONTROL) = EMAC_RXCONTROL_RXEN;
    }
    
    /**
     * \brief   API to write the TX HDP register. If transmit is enabled,
     *          write to the TX HDP will immediately start transmission.
     *          The data will be taken from the buffer pointer of the TX buffer
     *          descriptor written to the TX HDP
     *
     * \param   emacBase      Base Address of the EMAC Module Registers.\n
     * \param   descHdr       Address of the TX buffer descriptor
     * \param   channel       Channel Number
     *
     * \return  None
     *
     **/
    void EMACTxHdrDescPtrWrite(unsigned int emacBase, unsigned int descHdr,
                               unsigned int channel)
    {
        HWREG(emacBase + EMAC_TXHDP(channel)) = descHdr;
    }
    
    /**
     * \brief   API to write the RX HDP register. If receive is enabled,
     *          write to the RX HDP will enable data reception to point to
     *          the corresponding RX buffer descriptor's buffer pointer.
     *
     * \param   emacBase      Base Address of the EMAC Module Registers.\n
     * \param   descHdr       Address of the RX buffer descriptor
     * \param   channel       Channel Number
     *
     * \return  None
     *
     **/
    void EMACRxHdrDescPtrWrite(unsigned int emacBase, unsigned int descHdr,
                               unsigned int channel)
    {
        HWREG(emacBase + EMAC_RXHDP(channel)) = descHdr;
    }
    
    /**
     * \brief   This API Initializes the EMAC and EMAC Control modules. The
     *          EMAC Control module is reset, the CPPI RAM is cleared. also,
     *          all the interrupts are disabled. This API doesnot enable any
     *          interrupt or operation of the EMAC.
     *
     * \param   emacCtrlBase      Base Address of the EMAC Control module
     *                            registers.\n
     * \param   emacBase          Base address of the EMAC module registers
     *
     * \return  None
     *
     **/
    void EMACInit(unsigned int emacCtrlBase, unsigned int emacBase)
    {
        unsigned int cnt;
    
        /* Reset the EMAC Control Module. This clears the CPPI RAM also */
        HWREG(emacCtrlBase + EMAC_CTRL_SOFTRESET) = EMAC_CONTROL_RESET;
    
        while(HWREG(emacCtrlBase + EMAC_CTRL_SOFTRESET) & EMAC_CONTROL_RESET);
    
        /* Reset the EMAC Control Module. This clears the CPPI RAM also */
        HWREG(emacBase + EMAC_SOFTRESET) = EMAC_SOFT_RESET;
    
        while(HWREG(emacBase + EMAC_SOFTRESET) & EMAC_SOFT_RESET);
    
        HWREG(emacBase + EMAC_MACCONTROL)= 0;
        HWREG(emacBase + EMAC_RXCONTROL)= 0;
        HWREG(emacBase + EMAC_TXCONTROL)= 0;
    
        /* Initialize all the header descriptor pointer registers */
        for(cnt =  0; cnt< EMAC_MAX_HEADER_DESC; cnt++)
        {
            HWREG(emacBase + EMAC_RXHDP(cnt)) = 0;
            HWREG(emacBase + EMAC_TXHDP(cnt)) = 0;
            HWREG(emacBase + EMAC_RXCP(cnt)) = 0;
            HWREG(emacBase + EMAC_TXCP(cnt)) = 0;
            HWREG(emacBase + EMAC_RXFREEBUFFER(cnt)) = 0xFF;
        }
        /* Clear the interrupt enable for all the channels */
        HWREG(emacBase + EMAC_TXINTMASKCLEAR) = 0xFF;
        HWREG(emacBase + EMAC_RXINTMASKCLEAR) = 0xFF;
    
        HWREG(emacBase + EMAC_MACHASH1) = 0;
        HWREG(emacBase + EMAC_MACHASH2) = 0;
    
        HWREG(emacBase + EMAC_RXBUFFEROFFSET) = 0;
    }
    
    /**
     * \brief   Sets the MAC Address in MACSRCADDR registers.
     *
     * \param   emacBase      Base Address of the EMAC module registers.
     * \param   macAddr       Start address of a MAC address array.
     *                        The array[0] shall be the LSB of the MAC address
     *
     * \return  None
     *
     **/
    void  EMACMACSrcAddrSet(unsigned int emacBase, unsigned char *macAddr)
    {
        HWREG(emacBase + EMAC_MACSRCADDRHI) = macAddr[5] |(macAddr[4] << 8)
                                         |(macAddr[3] << 16) |(macAddr[2] << 24);
        HWREG(emacBase + EMAC_MACSRCADDRLO) = macAddr[1] | (macAddr[0] << 8);
    }
    
    /**
     * \brief   Sets the MAC Address in MACADDR registers.
     *
     * \param   emacBase      Base Address of the EMAC module registers.
     * \param   channel       Channel Number
     * \param   matchFilt     Match or Filter
     * \param   macAddr       Start address of a MAC address array.
     *                        The array[0] shall be the LSB of the MAC address
     *          matchFilt can take the following values \n
     *          EMAC_MACADDR_NO_MATCH_NO_FILTER - Address is not used to match
     *                                             or filter incoming packet. \n
     *          EMAC_MACADDR_FILTER - Address is used to filter incoming packets \n
     *          EMAC_MACADDR_MATCH - Address is used to match incoming packets \n
     *
     * \return  None
     *
     **/
    void EMACMACAddrSet(unsigned int emacBase, unsigned int channel,
                        unsigned char *macAddr, unsigned int matchFilt)
    {
        HWREG(emacBase + EMAC_MACINDEX) = channel;
    
        HWREG(emacBase + EMAC_MACADDRHI) = macAddr[5] |(macAddr[4] << 8)
                                         |(macAddr[3] << 16) |(macAddr[2] << 24);
        HWREG(emacBase + EMAC_MACADDRLO) = macAddr[1] | (macAddr[0] << 8)
                                         | matchFilt | (channel << 16);
    }
    
    /**
     * \brief   Acknowledges an interrupt processed to the EMAC Control Core.
     *
     * \param   emacBase      Base Address of the EMAC module registers.
     * \param   eoiFlag       Type of interrupt to acknowledge to the EMAC Control
     *                         module.
     *          eoiFlag can take the following values \n
     *             EMAC_INT_CORE0_TX - Core 0 TX Interrupt
     *             EMAC_INT_CORE1_TX - Core 1 TX Interrupt
     *             EMAC_INT_CORE2_TX - Core 2 TX Interrupt
     *             EMAC_INT_CORE0_RX - Core 0 RX Interrupt
     *             EMAC_INT_CORE1_RX - Core 1 RX Interrupt
     *             EMAC_INT_CORE2_RX - Core 2 RX Interrupt
     * \return  None
     * 
     **/
    void EMACCoreIntAck(unsigned int emacBase, unsigned int eoiFlag)
    {
        /* Acknowledge the EMAC Control Core */
        HWREG(emacBase + EMAC_MACEOIVECTOR) = eoiFlag;
    }
    
    /**
     * \brief   Writes the the TX Completion Pointer for a specific channel
     *
     * \param   emacBase      Base Address of the EMAC module registers.
     * \param   channel       Channel Number.
     * \param   comPtr        Completion Pointer Value to be written
     *
     * \return  None
     *
     **/
    void EMACTxCPWrite(unsigned int emacBase, unsigned int channel, unsigned int comPtr)
    {
        HWREG(emacBase + EMAC_TXCP(channel)) = comPtr;
    }
    
    /**
     * \brief   Writes the the RX Completion Pointer for a specific channel
     *
     * \param   emacBase      Base Address of the EMAC module registers.
     * \param   channel       Channel Number.
     * \param   comPtr        Completion Pointer Value to be written
     *
     * \return  None
     *
     **/
    void EMACRxCPWrite(unsigned int emacBase, unsigned int channel, unsigned int comPtr)
    {
        HWREG(emacBase + EMAC_RXCP(channel)) = comPtr;
    }
    
    /**
     * \brief   Acknowledges an interrupt processed to the EMAC module. After
     *          processing an interrupt, the last processed buffer descriptor is
     *          written to the completion pointer. Also this API acknowledges
     *          the EMAC Control Module that the RX interrupt is processed for
     *          a specified core
     *
     * \param   emacBase      Base Address of the EMAC module registers.
     * \param   channel       Channel Number
     * \param   comPtr        Completion Pointer value. This shall be the buffer
     *                        descriptor address last processed.
     * \param   eoiFlag       Type of interrupt to acknowledge to the EMAC Control
                              module.
     *          eoiFlag can take the following values \n
     *             EMAC_INT_CORE0_RX - Core 0 RX Interrupt
     *             EMAC_INT_CORE1_RX - Core 1 RX Interrupt
     *             EMAC_INT_CORE2_RX - Core 2 RX Interrupt
     * \return  None
     *
     **/
    void EMACRxIntAckToClear(unsigned int emacBase, unsigned int channel,
                             unsigned int comPtr, unsigned eoiFlag)
    {
        HWREG(emacBase + EMAC_RXCP(channel)) = comPtr;
    
        /* Acknowledge the EMAC Control Core */
        HWREG(emacBase + EMAC_MACEOIVECTOR) = eoiFlag;
    }
    
    /**
     * \brief   Enables a specific channel to receive broadcast frames
     *
     * \param   emacBase      Base Address of the EMAC module registers.
     * \param   channel       Channel Number.
     *
     * \return  None
     *
     **/
    void EMACRxBroadCastEnable(unsigned int emacBase, unsigned int channel)
    {
        HWREG(emacBase + EMAC_RXMBPENABLE) &= ~EMAC_RXMBPENABLE_RXBROADCH;
    
        HWREG(emacBase + EMAC_RXMBPENABLE) |=
                                  EMAC_RXMBPENABLE_RXBROADEN | 
                                  (channel << EMAC_RXMBPENABLE_RXBROADCH_SHIFT);
    }
    
    /**
     * \brief   Enables unicast for a specific channel
     *
     * \param   emacBase      Base Address of the EMAC module registers.
     * \param   channel       Channel Number.
     *
     * \return  None
     *
     **/
    void EMACRxUnicastSet(unsigned int emacBase, unsigned int channel)
    {
        HWREG(emacBase + EMAC_RXUNICASTSET) |= (1 << channel);
    }
    
    /**
     * \brief   Set the free buffers for a specific channel
     *
     * \param   emacBase      Base Address of the EMAC module registers.
     * \param   channel       Channel Number.
     * \param   nBuf          Number of free buffers
     *
     * \return  None
     *
     **/
    void EMACNumFreeBufSet(unsigned int emacBase, unsigned int channel,
                           unsigned int nBuf)
    {
        HWREG(emacBase + EMAC_RXFREEBUFFER(channel)) = nBuf;
    }
    
    /**
     * \brief   Gets the interrupt vectors of EMAC, which are pending
     *
     * \param   emacBase      Base Address of the EMAC module registers.
     *
     * \return  Vectors
     *
     **/
    unsigned int EMACIntVectorGet(unsigned int emacBase)
    {
        return (HWREG(emacBase + EMAC_MACINVECTOR));
    }
    
    /***************************** End Of File ***********************************/