/******************************************************************************/
/*                                                                            */
/*         Copyright(c) 2000-2002 by Ikanos Communications Inc.               */
/*                                                                            */
/*  All rights are reserved.  Reproduction in whole or in part is prohibited  */
/*  without the written consent of the copyright owner.                       */
/*                                                                            */
/*  The information and contents of this file are the proprietary information */
/*  of Ikanos Communication and may not be disclosed or used without the      */
/*  formal written approval of Ikanos Communication Inc.                      */
/*                                                                            */
/*  This Copyright notice may not be removed or modified without prior        */
/*  written consent of Ikanos Communications, Inc.                            */
/*                                                                            */
/******************************************************************************/
/*
**  Filename:    HostPtmfUtils.c
**
**  Project:     Ikanos INI ASIC (AMUR) Bring UP
**
**  Target:      MOTOROLA XPC855T based host board
**
**  Platform specific:
**    None.
**
**  Description:
**
**  $Revision: 1.2 $
**  $Date: 2006/12/12 10:53:07 $
**
**
**  **************************************************************************** 
**  Public Functions:
**
**  **************************************************************************** 
**  Private Functions:
**
**  **************************************************************************** 
**  Modification History:
**
**    Date         By     Description
**    -----------  ---    ------------------------------------------------------
**	  Jun-07-2002  SFA    Created
**    Jul-24-2002  SFA    Integration into new host code
**    Nov-06-2002  SFA    Adapted to the EIU of the CPE 2.0
*/
/******************************************************************************/
/*------------------------------------------------------------------------------
  INCLUDE FILES
  ----------------------------------------------------------------------------*/
#include <stdio.h>
#include "apiosmacro.h"
#include "HostPtmfApi.h"
#include "HostPtmfHwRegs.h"

/*------------------------------------------------------------------------------
  PRIVATE PREPROCESSOR CONSTANTS
  ----------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------
  PRIVATE PREPROCESSOR MACROS
  ----------------------------------------------------------------------------*/

/*------------------------------------------------------------------------------
  PRIVATE ENUMERATION DEFINITIONS
  ----------------------------------------------------------------------------*/

/*------------------------------------------------------------------------------
  PRIVATE TYPE DEFINITIONS
  ----------------------------------------------------------------------------*/

/*------------------------------------------------------------------------------
  PUBLIC VARIABLES DEFINITIONS
  ----------------------------------------------------------------------------*/
tsIposPtmfEnetAddrFilterCfg		tsEnetAddrFilterConfig;

/*------------------------------------------------------------------------------
  PRIVATE VARIABLES DEFINITIONS
  ----------------------------------------------------------------------------*/
static U16  s_abStaticAddr[]=
{
  0x280,  // SAT0
  0x283,  // SAT1
  0x286,  // SAT2
  0x289,  // SAT3
  0x28c,  // SAT4,
  0x290,  // SAT5,
  0x293,  // SAT6,
  0x296   // SAT7
};

/*------------------------------------------------------------------------------
  PRIVATE FUNCTION PROTOTYPE
  ----------------------------------------------------------------------------*/
extern U32 eiuPioRead (int BmeNum, unsigned long addr);
extern U32 eiuPioWrite (int BmeNum, unsigned long addr, unsigned long data);

/*------------------------------------------------------------------------------
  PUBLIC FUNCTION DEFINITIONS
  ----------------------------------------------------------------------------*/
/******************************************************************************/
void readFpga(U8 addr)
{
  U8 *baseAddr;

  U8 data2;
  baseAddr = (U8 *)0x09000000;
  data2 = *(addr + baseAddr);

  printf ("\n Reg(0x%x) = 0x%x \n",addr, data2);
}

/******************************************************************************/
void writeFpga(U8 addr ,U8 data)
{
  U8 *baseAddr;

  baseAddr = (U8 *) 0x09000000;
  *(baseAddr + addr) = data;
}   

/******************************************************************************
*                                                                             *
* Function.. : iposPtmfSemCreate              	   	                          *
*                                                   	                        *
* Purpose... : Program the EPLD register to set the INI mode. from amongst    *
*              RMII, SMII, SSSMII                                             *
*									                                                            *
* Parameters : Base address value                                             *
*                                                                             *
* Returns... : None                                                           *
*                                                                             *
******************************************************************************/
void 
  iposPtmfSemCreate (void)
{
  return;
}

/******************************************************************************
*                                                                             *
* Function.. : iposMdioRead                             	   	                *
*                                                   	                        *
* Purpose... : Reads the Ethernet PHY register through the MDIO interface     *
*									                                                            *
* Parameters : Pointer to the structure containing the port, register address *
*              and place to store the read data                               *
*                                                                             *
* Returns... : Success or Failure                                             *
*                                                                             *
******************************************************************************/

eIniRetCode
iposMdioRead (ptsHostIniMdioAddrData ptsIniReg)
{
  U32 uiEiuRegAddr, uiEiuRegData;
  U16 uiTimeout = 0;

  if (PTMF_BUS_HIC_PIO == (ptsIniReg->uiIniPhyAddr & PTMF_BUS_MASK))
  {
    // Reads the Ethernet PHY register through the MDIO interface of the AZTEC

#ifdef DEBUG_INI
    if (gbDebugLevel <= 0)
      printf("\nAztec Mdio Read ");
#endif //DEBUG_INI

    // Make the AZTEC PIO Address from the 10 bit index of the register.
    uiEiuRegAddr = MMDI_OP << 2;
    uiEiuRegAddr |= AZTEC_EIU_BASE_ADDR;

    // Wait till the Aztec's EIU is done with previous read/write operation
    do
    {
      uiEiuRegData = eiuPioRead (1, uiEiuRegAddr);

      uiTimeout++;
      if( uiTimeout > 300)
      {
        printf("\n Aztec EIU read timeout");
        return HOST_INI_REG_READ_TIMEOUT;
      }

    }while( (uiEiuRegData & MDIO_OP_READ) || (uiEiuRegData & MDIO_OP_WRITE));

    // Write the PHY reister address to the master MDIO address register of 
    // the AZTEC
    uiEiuRegAddr = MMDI_ADD; 
    uiEiuRegAddr = uiEiuRegAddr << 2;
    uiEiuRegAddr |= AZTEC_EIU_BASE_ADDR;

    uiEiuRegData  = (ptsIniReg->uiIniPhyAddr & 0x1f) << 5;
    uiEiuRegData |= (ptsIniReg->uiIniRegAddr & 0x1f);

    eiuPioWrite (1, uiEiuRegAddr, uiEiuRegData);

    // START the read operation by reading from the MDIO read operation
    // register of the AZTEC
    uiEiuRegAddr = MMDI_RD << 2;
    uiEiuRegAddr |= AZTEC_EIU_BASE_ADDR;
    
    uiEiuRegData = eiuPioRead (1, uiEiuRegAddr);

    uiEiuRegAddr = MMDI_OP << 2;
    uiEiuRegAddr |= AZTEC_EIU_BASE_ADDR;
    // Wait till the Aztec's EIU is done with previous read operation
    uiTimeout = 0;
    do
    {
      uiEiuRegData = eiuPioRead (1, uiEiuRegAddr);

      uiTimeout++;
      if( uiTimeout > 300)
      {
        printf("\n Aztec EIU read timeout");
        return HOST_INI_REG_READ_TIMEOUT;
      }

    }while(uiEiuRegData & MDIO_OP_READ); 

    uiEiuRegAddr = MMDI_RDAT << 2;
    uiEiuRegAddr |= AZTEC_EIU_BASE_ADDR;

    ptsIniReg->uiIniRdWrData = eiuPioRead (1, uiEiuRegAddr);

#ifdef DEBUG_INI
    if (gbDebugLevel <= 1)
      printf("\nREAD  %08x = %04x", (unsigned int)uiEiuRegAddr, ptsIniReg->uiIniRdWrData);
#endif //DEBUG_INI

    return HOST_INI_NO_ERROR;
  }
  else
    return HOST_INI_UNDEFINED_ERROR;
}

/******************************************************************************
*                                                                             *
* Function.. : iposMdioWrite                            	   	                *
*                                                   	                        *
* Purpose... : Writes to the Ethernet PHY register through the MDIO interface *
*									                                                            *
* Parameters : Pointer to the structure containing the port, register address *
*              and data to be written to the PHY                              *
*                                                                             *
* Returns... : Success or Failure                                             *
*                                                                             *
******************************************************************************/

eIniRetCode
iposMdioWrite (ptsHostIniMdioAddrData ptsIniReg)
{
  U32 uiEiuRegAddr, uiEiuRegData;
  U16 uiTimeout = 0;

  if (PTMF_BUS_HIC_PIO == (ptsIniReg->uiIniPhyAddr & PTMF_BUS_MASK))
  {
    // Reads the Ethernet PHY register through the MDIO interface of the AZTEC

#ifdef DEBUG_INI
    if (gbDebugLevel <= 0)
      printf("\nAztec Mdio Write ");
#endif //DEBUG_INI

    // Make the AZTEC PIO Address from the 10 bit index of the register.
    uiEiuRegAddr = MMDI_OP << 2;
    uiEiuRegAddr |= AZTEC_EIU_BASE_ADDR;

    // Wait till the Aztec's EIU is done with previous read/write operation
    do
    {
      uiEiuRegData = eiuPioRead (1, uiEiuRegAddr);

      uiTimeout++;
      if( uiTimeout > 300)
      {
        printf("\n Aztec EIU read timeout");
        return HOST_INI_REG_READ_TIMEOUT;
      }

    }while( (uiEiuRegData & MDIO_OP_READ) || (uiEiuRegData & MDIO_OP_WRITE));

    // Write the PHY register address to the master MDIO address register of 
    // the AZTEC
    uiEiuRegAddr = MMDI_ADD; 
    uiEiuRegAddr = uiEiuRegAddr << 2;
    uiEiuRegAddr |= AZTEC_EIU_BASE_ADDR;

    uiEiuRegData  = (ptsIniReg->uiIniPhyAddr & 0x1f) << 5;
    uiEiuRegData |= (ptsIniReg->uiIniRegAddr & 0x1f);

    eiuPioWrite (1, uiEiuRegAddr, uiEiuRegData);

    // START the write operation by writing to the MDIO Write operation
    // register of the AZTEC
    uiEiuRegAddr = MMDI_WDAT << 2;
    uiEiuRegAddr |= AZTEC_EIU_BASE_ADDR;

    uiEiuRegData = ptsIniReg->uiIniRdWrData;
    
    eiuPioWrite (1, uiEiuRegAddr, uiEiuRegData);

    uiEiuRegAddr = MMDI_OP << 2;
    uiEiuRegAddr |= AZTEC_EIU_BASE_ADDR;

    // Wait till the Aztec's EIU is done with write operation
    uiTimeout = 0;
    do
    {
      uiEiuRegData = eiuPioRead (1, uiEiuRegAddr);

      uiTimeout++;
      if( uiTimeout > 300)
      {
        printf("\n Aztec EIU read timeout");
        return HOST_INI_REG_READ_TIMEOUT;
      }

    }while(uiEiuRegData & MDIO_OP_WRITE); 

    return HOST_INI_NO_ERROR;
  }
  else
  {

#ifdef DEBUG_INI
    if (gbDebugLevel <= 5)
      printf("\n Error: Unknown Bus Type");
#endif //DEBUG_INI

    return HOST_INI_UNDEFINED_ERROR;
  }
}


/******************************************************************************
*                                                                             *
* Function.. : iposPtmfMdioRead                      	   	                    *
*                                                   	                        *
* Purpose... : Reads the INI register through the MDIO interface    	        *
*									                                                            *
* Parameters : Pointer to the structure containing the port, register address *
*              and place to store the read data                               *
*                                                                             *
* Returns... : Success or Failure                                             *
*                                                                             *
******************************************************************************/

eIniRetCode
iposPtmfMdioRead (ptsHostIniMdioAddrData ptsIniReg)
{
  U32 uiEiuRegAddr;
  
  if (PTMF_BUS_HIC_PIO == (ptsIniReg->bIniBaseAddr & PTMF_BUS_MASK))
  {
    
#ifdef DEBUG_INI
    if (gbDebugLevel <= 0)
      printf("\nAztec PIO Read ");
#endif //DEBUG_INI

    uiEiuRegAddr = ptsIniReg->uiIniRegAddr << 2;
    uiEiuRegAddr |= AZTEC_EIU_BASE_ADDR;

#ifdef DEBUG_INI
    if (gbDebugLevel <= 0)
      printf(" (0x%08x) ",(unsigned int)uiEiuRegAddr);
#endif //DEBUG_INI
   
    ptsIniReg->uiIniRdWrData = eiuPioRead (
                                (ptsIniReg->bIniBaseAddr & (~PTMF_BUS_MASK)), 
                                uiEiuRegAddr );
#ifdef DEBUG_INI
    if (gbDebugLevel <= 1)
      printf("\nREAD  %08x = %04x", (unsigned int)uiEiuRegAddr, ptsIniReg->uiIniRdWrData);
#endif //DEBUG_INI

    return HOST_INI_NO_ERROR;
  }
  else
  {
#ifdef DEBUG_INI
    if (gbDebugLevel <= 5)
      printf("\n Error: Unknown Bus Type");
#endif //DEBUG_INI

    return HOST_INI_UNDEFINED_ERROR;
  }
}

eIniRetCode
iposPtmfMdioRead1 (ptsHostIniMdioAddrData1 ptsIniReg1)
{

    ptsIniReg1->uiIniRdWrData = eiuPioRead (1, ptsIniReg1->uiIniRegAddr) ;

#ifdef DEBUG_INI
    if (gbDebugLevel <= 1)
      printf("\nREAD Reg:%08x Data= %08x", ptsIniReg1->uiIniRegAddr, ptsIniReg1->uiIniRdWrData);
#endif //DEBUG_INI

    return HOST_INI_NO_ERROR;
}
/******************************************************************************
*                                                                             *
* Function.. : iposPtmfMdioWrite1                      	   	                  *
*                                                   	                        *
* Purpose... : Write to the INI register through the MDIO interface  	        *
*									                                                            *
* Parameters : Pointer to the structure containing the port, register address *
*              and data to be written                                         *
*                                                                             *
* Returns... : Success or Failure                                             *
*                                                                             *
******************************************************************************/

eIniRetCode
iposPtmfMdioWrite1 (ptsHostIniMdioAddrData1 ptsIniReg1)
{

  eiuPioWrite (1, ptsIniReg1->uiIniRegAddr, ptsIniReg1->uiIniRdWrData) ;

#ifdef DEBUG_INI
    if (gbDebugLevel <= 1)
      printf("\nWRITE  Reg:[%08x]=%08x", ptsIniReg1->uiIniRegAddr, ptsIniReg1->uiIniRdWrData) ;
#endif //DEBUG_INI
    return HOST_INI_NO_ERROR;
}

/******************************************************************************
*                                                                             *
* Function.. : iposPtmfMdioWrite                      	   	                  *
*                                                   	                        *
* Purpose... : Write to the INI register through the MDIO interface  	        *
*									                                                            *
* Parameters : Pointer to the structure containing the port, register address *
*              and data to be written                                         *
*                                                                             *
* Returns... : Success or Failure                                             *
*                                                                             *
******************************************************************************/

eIniRetCode
iposPtmfMdioWrite (ptsHostIniMdioAddrData ptsIniReg)
{
  U32 uiEiuRegAddr, uiEiuRegData;

  if (PTMF_BUS_HIC_PIO == (ptsIniReg->bIniBaseAddr & PTMF_BUS_MASK))
  {

#ifdef DEBUG_INI
    if (gbDebugLevel <= 0)
      printf("\nAztec PIO Write ");
#endif //DEBUG_INI

    uiEiuRegAddr = ptsIniReg->uiIniRegAddr << 2;
    uiEiuRegAddr |= AZTEC_EIU_BASE_ADDR;

    uiEiuRegData = ptsIniReg->uiIniRdWrData;
    
    //printf("\nPIO reg address (0x%08x)",uiEiuRegAddr);

    eiuPioWrite ((ptsIniReg->bIniBaseAddr & (~PTMF_BUS_MASK)), 
                 uiEiuRegAddr,
                 uiEiuRegData);
#ifdef DEBUG_INI
    if (gbDebugLevel <= 1)
      printf("\nWRITE  %08x = %04x", (unsigned int)uiEiuRegAddr, (unsigned int)uiEiuRegData);
#endif //DEBUG_INI

    return HOST_INI_NO_ERROR;
  }
  else
  {
#ifdef DEBUG_INI
    if (gbDebugLevel <= 5)
      printf("\n Error: Unknown Bus Type");
#endif //DEBUG_INI

    return HOST_INI_UNDEFINED_ERROR;
  }
}

/******************************************************************************
*                                                                             *
* Function.. : iposPtmfResetPort                         	                    *
*                                                   	                        *
* Purpose... : Soft-reset the EIU port.                                       *
*									                                                            *
* Parameters : PTMF base address and Port address                             *
*                                                                             *
* Returns... : N/A                                                            *
*                                                                             *
******************************************************************************/
void 
  iposPtmfResetPort (U8 bPtmfBaseAddr, U16 bPortAddr)
{
  tsHostIniMdioAddrData   tsIniReg;

#ifdef DEBUG_INI
  if (gbDebugLevel <= 3)
    printf("\nINI ASIC RESET PORT (%02x-%04x)", bPtmfBaseAddr, bPortAddr);
#endif //DEBUG_INI

  // Before soft reset of the EIU, save the ethernet address filtering
  // related configuration
  iposPtmfReadAddrTabStatus(&tsEnetAddrFilterConfig);

  // Ethernet Port address set for access to the port specific MDIO registers.
  tsIniReg.bIniBaseAddr = bPtmfBaseAddr;
  tsIniReg.uiIniPhyAddr = bPortAddr;

  tsIniReg.uiIniRegAddr = CGRCR;
  iposPtmfMdioRead (&tsIniReg);

  tsIniReg.uiIniRdWrData |= SOFT_RESET;
  tsIniReg.uiIniRdWrData &= ~PSOFT_RESET;
  iposPtmfMdioWrite (&tsIniReg);

  tsIniReg.uiIniRdWrData |= PSOFT_RESET;
  iposPtmfMdioWrite (&tsIniReg);

  tsIniReg.uiIniRdWrData &= ~SOFT_RESET;
  iposPtmfMdioWrite (&tsIniReg);

  tsIniReg.uiIniRdWrData &= ~PSOFT_RESET;
  iposPtmfMdioWrite (&tsIniReg);

  tsIniReg.uiIniRdWrData |= PSOFT_RESET;
  iposPtmfMdioWrite (&tsIniReg);

  tsIniReg.uiIniRdWrData |= SOFT_RESET;
  iposPtmfMdioWrite (&tsIniReg);

  tsIniReg.uiIniRdWrData &= ~PSOFT_RESET;
  iposPtmfMdioWrite (&tsIniReg);

  // Re-configure the ethernet address filtering related configuration after 
  // soft reset of the EIU.
  iposPtmfAddrTabInit(&tsEnetAddrFilterConfig);
}

// ******** Functions for Ethernet Address Filtering ******** //

/******************************************************************************
*                                                                             *
* Function.. : iposPtmfAddrTabInit                                      	    *
*                                                   	                        *
* Purpose... : Initialise PTMF Address Filter table                  	        *
*									                           				                          *
* Parameters : Pointer to global parameter structure                          *
*                                                                             *
* Returns... : Error Code                                                     *
*                                                                             *
******************************************************************************/
eIniRetCode iposPtmfAddrTabInit (
    tsIposPtmfEnetAddrFilterCfg  *ptsEnetAddrFilterConfig)   
{
  tsHostIniMdioAddrData tsIniReg;
  U8      i, *pbEnetAddr;

  U16     uiEnetAddrBits00_15;
  U16     uiEnetAddrBits16_31;
  U16     uiEnetAddrBits32_47;


  /* if the config structure pointer passed is NULL, use default              */
  if (ptsEnetAddrFilterConfig == NULL)
  {
#ifdef DEBUG_INI
    if (gbDebugLevel <= 5)
      printf("\nEnet Address Filter Init: Illegal Structure Pointer");
#endif //DEBUG_INI

    return HOST_INI_UNDEFINED_ERROR;
  }	

#ifdef DEBUG_INI
    if (gbDebugLevel <= 3)
    {
      printf ("\n tsIposPtmfEnetAddrFilterCfg.....");
      printf ("\n |->bAddrFilterEn      = %i", ptsEnetAddrFilterConfig->bAddrFilterEn);
      printf ("\n |->bLearningEn        = %i", ptsEnetAddrFilterConfig->bLearningEn);
      printf ("\n |->bAgingEn           = %i", ptsEnetAddrFilterConfig->bAgingEn);
      printf ("\n |->bMultiCastFilterEn = %i", ptsEnetAddrFilterConfig->bMultiCastFilterEn);
      printf ("\n |->bBroadCastFilterEn = %i", ptsEnetAddrFilterConfig->bBroadCastFilterEn);
      printf ("\n |->uiAgingCount       = %i", ptsEnetAddrFilterConfig->uiAgingCount);
      printf ("\n |->uiAddrEntryEn      = 0x%04x", ptsEnetAddrFilterConfig->uiAddrEntryEn);
      printf ("\n `->bStaticAddrCount   = %i\n", ptsEnetAddrFilterConfig->bStaticAddrCount);

      for (i = 0; i < MAX_FILTER_TABLE_ENTRY; i++)
      {
        printf ("\n Ethernet Address [%i] = %02x.%02x.%02x.%02x.%02x.%02x",
                i+1,
                ptsEnetAddrFilterConfig->abEnetAddr[i][0],
                ptsEnetAddrFilterConfig->abEnetAddr[i][1],
                ptsEnetAddrFilterConfig->abEnetAddr[i][2],
                ptsEnetAddrFilterConfig->abEnetAddr[i][3],
                ptsEnetAddrFilterConfig->abEnetAddr[i][4],
                ptsEnetAddrFilterConfig->abEnetAddr[i][5]);
      }
      printf ("\n");
    }
#endif //DEBUG_INI

  tsIniReg.bIniBaseAddr = PTMF_MDIO_ADDR;
  tsIniReg.uiIniRegAddr = ACR;

  iposPtmfMdioRead ( &tsIniReg );

  if (ptsEnetAddrFilterConfig->bAddrFilterEn)
    tsIniReg.uiIniRdWrData |= ADDRFILT_EN;
  else
    tsIniReg.uiIniRdWrData &= ~ADDRFILT_EN;

  if (ptsEnetAddrFilterConfig->bAgingEn)
    tsIniReg.uiIniRdWrData |= AGING_EN;
  else
    tsIniReg.uiIniRdWrData &= ~AGING_EN;

  if (ptsEnetAddrFilterConfig->bLearningEn)
    tsIniReg.uiIniRdWrData |= LEARNING_EN;
  else
    tsIniReg.uiIniRdWrData &= ~LEARNING_EN;

  if (ptsEnetAddrFilterConfig->bMultiCastFilterEn)
    tsIniReg.uiIniRdWrData |= MLTCST_CONFIG;
  else
    tsIniReg.uiIniRdWrData &= ~MLTCST_CONFIG;

  if (ptsEnetAddrFilterConfig->bBroadCastFilterEn)
    tsIniReg.uiIniRdWrData |= BRDCST_CONFIG;
  else
    tsIniReg.uiIniRdWrData &= ~BRDCST_CONFIG;

  tsIniReg.uiIniRegAddr = ACR;
  iposPtmfMdioWrite ( &tsIniReg );

  tsIniReg.uiIniRegAddr = AACR;
  tsIniReg.uiIniRdWrData = ptsEnetAddrFilterConfig->uiAgingCount;

  iposPtmfMdioWrite ( &tsIniReg );

  pbEnetAddr = (U8 *)&(ptsEnetAddrFilterConfig->abEnetAddr);

  for (i = 0; i < MAX_FILTER_TABLE_ENTRY; i++)
  {
    uiEnetAddrBits32_47 = *pbEnetAddr;
    uiEnetAddrBits32_47 <<= 8;
    pbEnetAddr++;
    uiEnetAddrBits32_47 |= *pbEnetAddr;
    pbEnetAddr++;

    uiEnetAddrBits16_31 = *pbEnetAddr;
    uiEnetAddrBits16_31 <<= 8;
    pbEnetAddr++;
    uiEnetAddrBits16_31 |= *pbEnetAddr;
    pbEnetAddr++;

    uiEnetAddrBits00_15 = *pbEnetAddr;
    uiEnetAddrBits00_15 <<= 8;
    pbEnetAddr++;
    uiEnetAddrBits00_15 |= *pbEnetAddr;
    pbEnetAddr++;

    tsIniReg.uiIniRegAddr   = s_abStaticAddr[i];
    tsIniReg.uiIniRdWrData  = uiEnetAddrBits00_15;
    iposPtmfMdioWrite ( &tsIniReg );

    tsIniReg.uiIniRegAddr++;
    tsIniReg.uiIniRdWrData = uiEnetAddrBits16_31;
    iposPtmfMdioWrite ( &tsIniReg );

    tsIniReg.uiIniRegAddr++;
    tsIniReg.uiIniRdWrData = uiEnetAddrBits32_47;
    iposPtmfMdioWrite ( &tsIniReg );
  }
  // Address filtering static address enable register (ASER)
  tsIniReg.uiIniRegAddr   = ASER;
  tsIniReg.uiIniRdWrData  = ptsEnetAddrFilterConfig->uiAddrEntryEn;
  iposPtmfMdioWrite ( &tsIniReg );

  return HOST_INI_NO_ERROR;
}

/******************************************************************************
*                                                                             *
* Function.. : iposPtmfAddAddrEntry                                      	    *
*                                                   	                        *
* Purpose... : Add a static address to the filter table              	        *
*									                           				                          *
* Parameters : Pointer to a 6 byte array.and the table index                  *
*                                                                             *
* Returns... : None                                                           *
*                                                                             *
******************************************************************************/
eIniRetCode iposPtmfAddAddrEntry (U8 bTableIndex, U8 *pbEnetAddr)
{
  tsHostIniMdioAddrData tsIniReg;
  
  U16                   uiEnetAddrBits00_15;
  U16                   uiEnetAddrBits16_31;
  U16                   uiEnetAddrBits32_47;

  U8                    bAddrEnable =0x1;

  if (bTableIndex >= MAX_FILTER_TABLE_ENTRY)
    return HOST_INI_UNDEFINED_ERROR;

  tsIniReg.bIniBaseAddr   = PTMF_MDIO_ADDR;

#ifdef DEBUG_INI
  if (gbDebugLevel <= 3)
    printf("\n iposPtmfAddAddrEntry %i; %08x", bTableIndex, (unsigned int)pbEnetAddr);
#endif //DEBUG_INI

  uiEnetAddrBits32_47 = *pbEnetAddr;
  uiEnetAddrBits32_47 <<= 8;
  pbEnetAddr++;
  uiEnetAddrBits32_47 |= *pbEnetAddr;
  pbEnetAddr++;

  uiEnetAddrBits16_31 = *pbEnetAddr;
  uiEnetAddrBits16_31 <<= 8;
  pbEnetAddr++;
  uiEnetAddrBits16_31 |= *pbEnetAddr;
  pbEnetAddr++;

  uiEnetAddrBits00_15 = *pbEnetAddr;
  uiEnetAddrBits00_15 <<= 8;
  pbEnetAddr++;
  uiEnetAddrBits00_15 |= *pbEnetAddr;
  pbEnetAddr++;

  tsIniReg.uiIniRegAddr   = s_abStaticAddr[bTableIndex];
  tsIniReg.uiIniRdWrData  = uiEnetAddrBits00_15;

#ifdef DEBUG_INI
  if (gbDebugLevel <= 3)
    printf("\n Reg Addr = %04x; Data = %04x ",tsIniReg.uiIniRegAddr,
                                             tsIniReg.uiIniRdWrData );
#endif //DEBUG_INI

  iposPtmfMdioWrite ( &tsIniReg );

  tsIniReg.uiIniRegAddr++;

  tsIniReg.uiIniRdWrData = uiEnetAddrBits16_31;

#ifdef DEBUG_INI
  if (gbDebugLevel <= 3)
    printf("\n Reg Addr = %04x; Data = %04x ",tsIniReg.uiIniRegAddr,
                                             tsIniReg.uiIniRdWrData );
#endif //DEBUG_INI

  iposPtmfMdioWrite ( &tsIniReg );

  tsIniReg.uiIniRegAddr++;

  tsIniReg.uiIniRdWrData = uiEnetAddrBits32_47;

#ifdef DEBUG_INI
  if (gbDebugLevel <= 3)
    printf("\n Reg Addr = %04x; Data = %04x ",tsIniReg.uiIniRegAddr,
                                             tsIniReg.uiIniRdWrData );
#endif //DEBUG_INI

  iposPtmfMdioWrite ( &tsIniReg );

  // Address filtering static address enable register (ASER)
  tsIniReg.uiIniRegAddr = ASER;
  iposPtmfMdioRead ( &tsIniReg );

  bAddrEnable <<= bTableIndex;

  tsIniReg.uiIniRdWrData |= bAddrEnable;

#ifdef DEBUG_INI
  if (gbDebugLevel <= 2)
  {
    printf("\n Add Address Entry");
    printf("\n Reg Addr = %04x; Data = %04x ",tsIniReg.uiIniRegAddr,
                                             tsIniReg.uiIniRdWrData );
  }
#endif //DEBUG_INI

  iposPtmfMdioWrite ( &tsIniReg );

  return HOST_INI_NO_ERROR;

}

/******************************************************************************
*                                                                             *
* Function.. : iposPtmfRemoveAddrEntry                                   	    *
*                                                   	                        *
* Purpose... : Remove a static address from the filter table         	        *
*									                           				                          *
* Parameters : Table Index                                                    *
*                                                                             *
* Returns... : None                                                           *
*                                                                             *
******************************************************************************/
eIniRetCode iposPtmfRemoveAddrEntry (U8 bTableIndex)
{
  tsHostIniMdioAddrData tsIniReg;
  U8                    bAddrEnable =0x1;

  if (bTableIndex >= MAX_FILTER_TABLE_ENTRY)
    return HOST_INI_UNDEFINED_ERROR;
  
  tsIniReg.bIniBaseAddr   = PTMF_MDIO_ADDR;

  // Address filtering static address enable register (ASER)
  tsIniReg.uiIniRegAddr = ASER;
  iposPtmfMdioRead ( &tsIniReg );

  bAddrEnable <<= bTableIndex;
  tsIniReg.uiIniRdWrData &= ~bAddrEnable;

#ifdef DEBUG_INI
  if (gbDebugLevel <= 2)
  {
    printf("\n Remove Address Entry");
    printf("\n Reg Addr = %04x; Data = %04x ", tsIniReg.uiIniRegAddr,
                                               tsIniReg.uiIniRdWrData );
  }
#endif //DEBUG_INI
  iposPtmfMdioWrite ( &tsIniReg );

  tsIniReg.uiIniRegAddr   = s_abStaticAddr[bTableIndex];
  tsIniReg.uiIniRdWrData  = 0;
  iposPtmfMdioWrite ( &tsIniReg );

  tsIniReg.uiIniRegAddr++;
  tsIniReg.uiIniRdWrData  = 0;
  iposPtmfMdioWrite ( &tsIniReg );

  tsIniReg.uiIniRegAddr++;
  tsIniReg.uiIniRdWrData  = 0;
  iposPtmfMdioWrite ( &tsIniReg );

  return HOST_INI_NO_ERROR;

}

/******************************************************************************
*                                                                             *
* Function.. : iposPtmfReadAddrEntry                                    	    *
*                                                   	                        *
* Purpose... : Read a static address from the filter table          	        *
*									                           				                          *
* Parameters : Pointer to a 6 byte array.and the table index                  *
*                                                                             *
* Returns... : None                                                           *
*                                                                             *
******************************************************************************/
eIniRetCode iposPtmfReadAddrEntry (U8 bTableIndex, U8 *pbEnetAddr)
{
  tsHostIniMdioAddrData tsIniReg;
  
  U16                   uiEnetAddrBits00_15;
  U16                   uiEnetAddrBits16_31;
  U16                   uiEnetAddrBits32_47;

  if (bTableIndex >= MAX_FILTER_TABLE_ENTRY)
    return HOST_INI_UNDEFINED_ERROR;

  tsIniReg.bIniBaseAddr   = PTMF_MDIO_ADDR;

#ifdef DEBUG_INI
  if (gbDebugLevel <= 3)
    printf("\n iposPtmfAddAddrEntry %i; %08x", bTableIndex, (unsigned int)pbEnetAddr);
#endif //DEBUG_INI

  tsIniReg.uiIniRegAddr   = s_abStaticAddr[bTableIndex];
  iposPtmfMdioRead ( &tsIniReg );
  uiEnetAddrBits00_15 = tsIniReg.uiIniRdWrData;

#ifdef DEBUG_INI
  if (gbDebugLevel <= 3)
    printf("\n Reg Addr = %04x; Data = %04x ",tsIniReg.uiIniRegAddr,
                                             tsIniReg.uiIniRdWrData );
#endif //DEBUG_INI

  tsIniReg.uiIniRegAddr++;

  iposPtmfMdioRead ( &tsIniReg );
  uiEnetAddrBits16_31 = tsIniReg.uiIniRdWrData;

#ifdef DEBUG_INI
  if (gbDebugLevel <= 3)
    printf("\n Reg Addr = %04x; Data = %04x ",tsIniReg.uiIniRegAddr,
                                             tsIniReg.uiIniRdWrData );
#endif //DEBUG_INI

  tsIniReg.uiIniRegAddr++;
  iposPtmfMdioRead ( &tsIniReg );
  uiEnetAddrBits32_47 = tsIniReg.uiIniRdWrData;

#ifdef DEBUG_INI
  if (gbDebugLevel <= 3)
    printf("\n Reg Addr = %04x; Data = %04x ",tsIniReg.uiIniRegAddr,
                                             tsIniReg.uiIniRdWrData );
#endif //DEBUG_INI

  *pbEnetAddr = (U8)((uiEnetAddrBits32_47 >> 8) & 0x00ff);
  pbEnetAddr++;
  *pbEnetAddr = (U8)(uiEnetAddrBits32_47 & 0x00ff);
  pbEnetAddr++;

  *pbEnetAddr = (U8)((uiEnetAddrBits16_31 >> 8) & 0x00ff);
  pbEnetAddr++;
  *pbEnetAddr = (U8)(uiEnetAddrBits16_31 & 0x00ff);
  pbEnetAddr++;

  *pbEnetAddr = (U8)((uiEnetAddrBits00_15 >> 8) & 0x00ff);
  pbEnetAddr++;
  *pbEnetAddr = (U8)(uiEnetAddrBits00_15 & 0x00ff);

  return HOST_INI_NO_ERROR;
}

/******************************************************************************
*                                                                             *
* Function.. : iposPtmfReadAddrTabStatus                                 	    *
*                                                   	                        *
* Purpose... : Update the structure with the EIU Address Filter table	and     *
*              another configurations                                         *
*									                           				                          *
* Parameters : Pointer to global parameter structure                          *
*                                                                             *
* Returns... : Error Code                                                     *
*                                                                             *
******************************************************************************/

eIniRetCode iposPtmfReadAddrTabStatus (
    tsIposPtmfEnetAddrFilterCfg  *ptsEnetAddrFilterConfig)   
{
  tsHostIniMdioAddrData tsIniReg;
  U8      i, *pbEnetAddr;

  U16     uiEnetAddrBits00_15;
  U16     uiEnetAddrBits16_31;
  U16     uiEnetAddrBits32_47;

  /* if the config structure pointer passed is NULL, use default              */
  if (ptsEnetAddrFilterConfig == NULL)
  {
#ifdef DEBUG_INI
    if (gbDebugLevel <= 5)
      printf("\nEnet Address Filter Config Read: Illegal Structure Pointer");
#endif //DEBUG_INI

    return HOST_INI_UNDEFINED_ERROR;
  }	

  tsIniReg.bIniBaseAddr = PTMF_MDIO_ADDR;

  tsIniReg.uiIniRegAddr = ACR;
  iposPtmfMdioRead ( &tsIniReg );

  if (tsIniReg.uiIniRdWrData & ADDRFILT_EN)
    ptsEnetAddrFilterConfig->bAddrFilterEn = 1;
  else
    ptsEnetAddrFilterConfig->bAddrFilterEn = 0;

  if (tsIniReg.uiIniRdWrData & AGING_EN)
    ptsEnetAddrFilterConfig->bAgingEn = 1;
  else
    ptsEnetAddrFilterConfig->bAgingEn = 0;

  if (tsIniReg.uiIniRdWrData & LEARNING_EN)
    ptsEnetAddrFilterConfig->bLearningEn = 1;
  else
    ptsEnetAddrFilterConfig->bLearningEn = 0;

  if (tsIniReg.uiIniRdWrData & MLTCST_CONFIG)
    ptsEnetAddrFilterConfig->bMultiCastFilterEn = 1;
  else
    ptsEnetAddrFilterConfig->bMultiCastFilterEn = 0;

  if (tsIniReg.uiIniRdWrData & BRDCST_CONFIG)
    ptsEnetAddrFilterConfig->bBroadCastFilterEn = 1;
  else
    ptsEnetAddrFilterConfig->bBroadCastFilterEn = 0;

  if (tsIniReg.uiIniRdWrData & AGING_EN)
    ptsEnetAddrFilterConfig->bAgingEn = 1;
  else
    ptsEnetAddrFilterConfig->bAgingEn = 0;


  // Read the Aging COunt register.
  tsIniReg.uiIniRegAddr = AACR;
  iposPtmfMdioRead ( &tsIniReg );
  ptsEnetAddrFilterConfig->uiAgingCount = tsIniReg.uiIniRdWrData;

  // Now read the static address table
  pbEnetAddr = (U8 *)&(ptsEnetAddrFilterConfig->abEnetAddr);
  for (i = 0; i < MAX_FILTER_TABLE_ENTRY; i++)
  {

    tsIniReg.uiIniRegAddr   = s_abStaticAddr[i];
    iposPtmfMdioRead ( &tsIniReg );
    uiEnetAddrBits00_15 = tsIniReg.uiIniRdWrData;

    tsIniReg.uiIniRegAddr++;
    iposPtmfMdioRead ( &tsIniReg );
    uiEnetAddrBits16_31 = tsIniReg.uiIniRdWrData;

    tsIniReg.uiIniRegAddr++;
    iposPtmfMdioRead ( &tsIniReg );
    uiEnetAddrBits32_47 = tsIniReg.uiIniRdWrData;

    *pbEnetAddr = (U8)((uiEnetAddrBits32_47 >> 8) & 0x00ff);
    pbEnetAddr++;
    *pbEnetAddr = (U8)(uiEnetAddrBits32_47 & 0x00ff);
    pbEnetAddr++;

    *pbEnetAddr = (U8)((uiEnetAddrBits16_31 >> 8) & 0x00ff);
    pbEnetAddr++;
    *pbEnetAddr = (U8)(uiEnetAddrBits16_31 & 0x00ff);
    pbEnetAddr++;

    *pbEnetAddr = (U8)((uiEnetAddrBits00_15 >> 8) & 0x00ff);
    pbEnetAddr++;
    *pbEnetAddr = (U8)(uiEnetAddrBits00_15 & 0x00ff);
    pbEnetAddr++;

  }
  // Address filtering static address enable register (ASER)
  tsIniReg.uiIniRegAddr   = ASER;
  iposPtmfMdioRead ( &tsIniReg );
  ptsEnetAddrFilterConfig->uiAddrEntryEn = tsIniReg.uiIniRdWrData;

#ifdef DEBUG_INI
  if (gbDebugLevel <= 3)
  {
    printf ("\n tsIposPtmfEnetAddrFilterCfg.....");
    printf ("\n |->bAddrFilterEn      = %i", ptsEnetAddrFilterConfig->bAddrFilterEn);
    printf ("\n |->bLearningEn        = %i", ptsEnetAddrFilterConfig->bLearningEn);
    printf ("\n |->bAgingEn           = %i", ptsEnetAddrFilterConfig->bAgingEn);
    printf ("\n |->bMultiCastFilterEn = %i", ptsEnetAddrFilterConfig->bMultiCastFilterEn);
    printf ("\n |->bBroadCastFilterEn = %i", ptsEnetAddrFilterConfig->bBroadCastFilterEn);
    printf ("\n |->uiAgingCount       = %i", ptsEnetAddrFilterConfig->uiAgingCount);
    printf ("\n |->uiAddrEntryEn      = 0x%04x", ptsEnetAddrFilterConfig->uiAddrEntryEn);
    printf ("\n |->bStaticAddrCount   = %i", ptsEnetAddrFilterConfig->bStaticAddrCount);
    printf ("\n `->bMaxReadCount      = %i\n", ptsEnetAddrFilterConfig->bMaxReadCount);

    for (i = 0; i < MAX_FILTER_TABLE_ENTRY; i++)
    {
      printf ("\n Ethernet Address [%i] = %02x.%02x.%02x.%02x.%02x.%02x",
              i+1,
              ptsEnetAddrFilterConfig->abEnetAddr[i][0],
              ptsEnetAddrFilterConfig->abEnetAddr[i][1],
              ptsEnetAddrFilterConfig->abEnetAddr[i][2],
              ptsEnetAddrFilterConfig->abEnetAddr[i][3],
              ptsEnetAddrFilterConfig->abEnetAddr[i][4],
              ptsEnetAddrFilterConfig->abEnetAddr[i][5]);
    }
    printf ("\n");
  }
#endif //DEBUG_INI

  // Number of address programmable to the user: BME-CPE 2.0 = 8
  ptsEnetAddrFilterConfig->bStaticAddrCount = MAX_FILTER_TABLE_ENTRY;
  ptsEnetAddrFilterConfig->bMaxReadCount    = MAX_FILTER_TABLE_ENTRY;

  return HOST_INI_NO_ERROR;
}


/******************************************************************************
*                                                                             *
* Function.. : iposPtmfEnetAddrFilterClearTable                          	    *
*                                                   	                        *
* Purpose... : Flush the Ethernet MAC Address learned table          	        *
*									                           				                          *
* Parameters : None                                                           *
*                                                                             *
* Returns... : Error Code                                                     *
*                                                                             *
******************************************************************************/

eIniRetCode 
  iposPtmfEnetAddrFilterClearTable ( void)
{
  tsHostIniMdioAddrData tsIniReg;
  U8  i;

#ifdef DEBUG_INI
    if (gbDebugLevel <= 3)
      printf("\nFlush the Learned Address Table");
#endif //DEBUG_INI

  tsIniReg.bIniBaseAddr = PTMF_MDIO_ADDR;
  tsIniReg.uiIniRegAddr = ACR;

  iposPtmfMdioRead ( &tsIniReg );
  tsIniReg.uiIniRdWrData |= FLUSH_TABLE;

  iposPtmfMdioWrite ( &tsIniReg );

  for (i = 0; i < 0xff; i++);

  iposPtmfMdioRead ( &tsIniReg );
  tsIniReg.uiIniRdWrData &= ~FLUSH_TABLE;

  iposPtmfMdioWrite ( &tsIniReg );

  return HOST_INI_NO_ERROR;
}

#if defined(CPE_30)
/******************************************************************************
*                                                                             *
* Function.. : iposPtmfReadLearnedAddr                                   	    *
*                                                   	                        *
* Purpose... : Read a Learned address from the filter table          	        *
*									                           				                          *
* Parameters : Pointer to a 6 byte array.and the table index                  *
*                                                                             *
* Returns... : None                                                           *
*                                                                             *
******************************************************************************/
eIniRetCode iposPtmfReadLearnedAddr (U8 bTableIndex, U8 *pbEnetAddr)
{
  tsHostIniMdioAddrData tsIniReg;
  
  U16                   uiEnetAddrBits00_15;
  U16                   uiEnetAddrBits16_31;
  U16                   uiEnetAddrBits32_47;

  tsIniReg.bIniBaseAddr   = PTMF_MDIO_ADDR;

#ifdef DEBUG_INI
  if (gbDebugLevel <= 3)
    printf("\n iposPtmfReadLearnedAddr %i; %08x", bTableIndex, (unsigned int)pbEnetAddr);
#endif //DEBUG_INI

  tsIniReg.uiIniRegAddr   = LTRAD;
  tsIniReg.uiIniRdWrData  = bTableIndex & 0x1f;
  iposPtmfMdioWrite ( &tsIniReg );
  
  iposPtmfMdioRead ( &tsIniReg );
  while(!(tsIniReg.uiIniRdWrData & 0x8000))
    iposPtmfMdioRead ( &tsIniReg );

  if (tsIniReg.uiIniRdWrData & 0x4000)
  {
    tsIniReg.uiIniRegAddr   = LTRR0;
    iposPtmfMdioRead ( &tsIniReg );
    uiEnetAddrBits00_15 = tsIniReg.uiIniRdWrData;

#ifdef DEBUG_INI
    if (gbDebugLevel <= 3)
      printf("\n Reg Addr = %04x; Data = %04x ",tsIniReg.uiIniRegAddr,
                                                tsIniReg.uiIniRdWrData );
#endif //DEBUG_INI


    tsIniReg.uiIniRegAddr++;

    iposPtmfMdioRead ( &tsIniReg );
    uiEnetAddrBits16_31 = tsIniReg.uiIniRdWrData;

#ifdef DEBUG_INI
    if (gbDebugLevel <= 3)
      printf("\n Reg Addr = %04x; Data = %04x ",tsIniReg.uiIniRegAddr,
                                               tsIniReg.uiIniRdWrData );
#endif //DEBUG_INI

    tsIniReg.uiIniRegAddr++;
    iposPtmfMdioRead ( &tsIniReg );
    uiEnetAddrBits32_47 = tsIniReg.uiIniRdWrData;

#ifdef DEBUG_INI
    if (gbDebugLevel <= 3)
      printf("\n Reg Addr = %04x; Data = %04x ",tsIniReg.uiIniRegAddr,
                                               tsIniReg.uiIniRdWrData );
#endif //DEBUG_INI

    *pbEnetAddr = (U8)((uiEnetAddrBits32_47 >> 8) & 0x00ff);
    pbEnetAddr++;
    *pbEnetAddr = (U8)(uiEnetAddrBits32_47 & 0x00ff);
    pbEnetAddr++;

    *pbEnetAddr = (U8)((uiEnetAddrBits16_31 >> 8) & 0x00ff);
    pbEnetAddr++;
    *pbEnetAddr = (U8)(uiEnetAddrBits16_31 & 0x00ff);
    pbEnetAddr++;

    *pbEnetAddr = (U8)((uiEnetAddrBits00_15 >> 8) & 0x00ff);
    pbEnetAddr++;
    *pbEnetAddr = (U8)(uiEnetAddrBits00_15 & 0x00ff);

    return HOST_INI_NO_ERROR;
  }
  else
    return HOST_INI_INVALID_ADDRESS_ENTRY;
}

#endif //#if defined(CPE_30)

/*------------------------------------------------------------------------------
                                 END OF FILE
------------------------------------------------------------------------------*/
