/**************************************************************
***************************************************************
**
** BME Firmware, Copyright (C) 2000-2002
** Ikanos Communication, Fremont, CA 
** All rights reserved.
**
** 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
**
***************************************************************

$Revision: 1.1 $
$Date: 2006/10/16 04:34:50 $
**************************************************************/

#include "bme_app.h"
#include "mem.h"
#include "hostType.h"

#define	CKM_PCR					0xE0070008	/* GL		Clock module config options*/

#define ATM_MAX_PORT  		(32)
#define ATM_MASK      		(32 - 1)
#define ATM_PORT_NOT_USED 	(0xFF)

#define ATM_STATE_OFFSET	(0x400)

#define FAST_PATH_LOCKED		(1)
#define INLV_PATH_LOCKED		(2)


u8 atmPortI2Ni[ATM_MAX_PORT];
u8 atmPortF2Ni[ATM_MAX_PORT];

void BmeNIenableCh2(u8 port);

/*
************************************************************************
	Function: BmeNIreset
	
	Description: Reset network interface.
    
  Input Value: none
      
  Output Value: none
	
	Return Value: none
************************************************************************
*/
void BmeNIreset(void)
{
 int i;
 int iChNum;
 int iUtopiaAddr;
   	iChNum      = 31;
	iUtopiaAddr = 63;

   	/* 
	** set fast & interleave xfifo for ch-31 to both src/dest points to xtensa and also 
	** make the fifo to be invalid. Assign all the ports that are not configured 
	** to this xfifo, SCR # 179 
	*/
	writePIO_SingleRegChannel((int *)(XFIFOF_CXFT_B), iChNum, 0);
	writePIO_SingleRegChannel((int *)(XFIFOF_CXFT_A), iChNum, (1 << 2) + (1 << 1) + 0);
	writePIO_SingleRegChannel((int *)(XFIFOI_CXFT_B), iChNum, 0);
	writePIO_SingleRegChannel((int *)(XFIFOI_CXFT_A), iChNum, (1 << 2) + (1 << 1) + 0);
   	
	/* disable both TX & RX network interfaces */
	for (i = 0; i < ATM_MAX_PORT; i++)
	{
		/* set all utopia address to 63 */
		writePIO_SingleRegChannel ((int *) TNICH_FAST, i, (iUtopiaAddr << 25));
		writePIO_SingleRegChannel ((int *) TNICH_INLV, i, (iUtopiaAddr << 25));

		/* set all channel number to 31 */
		writePIO_SingleRegChannel ((int *) TNIPHY_LOW, i, (iChNum << 26));
		writePIO_SingleRegChannel ((int *) TNIPHY_HIGH, i, (iChNum << 26));

		/* turn all utopia off */
		writePIO_SingleRegChannel ((int *) TNIPHY_LOW_ONOFF, i, 0);
		writePIO_SingleRegChannel ((int *) TNIPHY_HIGH_ONOFF, i, 0);

		writePIO_SingleRegChannel ((int *) PHY_CTRL_A, i, 0);
		writePIO_SingleRegChannel ((int *) PHY_CTRL_B, i, 0);
	}

	for( i=0; i < ATM_MAX_PORT; i++){
		atmPortI2Ni[i] = ATM_PORT_NOT_USED;
		atmPortF2Ni[i] = ATM_PORT_NOT_USED;
	}

  // Set BME clock to 148MHz
  writePIO_SingleRegChannel ((int *) CKM_PCR, 0, 0x147);
}

/*
************************************************************************
	Function: BmeNIconfigUtopia
	
	Description: Configure network interface.
    
  Input Value: level - network interface operation level
               extendedMode - extended mode enable flag
               removeHec - HEC byte remove flag
               cellSize - ATM cell size
    
  Output Value: none
	
	Return Value: none
************************************************************************
*/
void BmeNIconfigUtopia(u8 level, u8 extendedMode, u8 removeHec, u8 cellSize)
{
	u32 level3CellSize = 0;
	if( level && cellSize==52)
		level3CellSize = (u32) 1 << 29;

	writePIO_SingleRegChannel ((int *)TNICELL_SIZE,    0,    (cellSize << 24));

	writePIO_SingleRegChannel ((int *)TNILEVEL_ONFO, 0, (level << 31)+(((extendedMode & 0x1) << 30)) + level3CellSize);

	writePIO_SingleRegChannel ((int *)RNI_MCR,  0,  (level<<31)+((extendedMode & 0x1)<<30)+(removeHec<<29)+((cellSize<<16)));
}

/*
************************************************************************
	Function: BmeNIconfigCh
	
	Description: Configure network interface channel.  This function will
               not validate the input parameters.
    
  Input Value: portNum - xDSL port number
               fastChnlNum - fast path phy number (< 0 - not selected)
               ilvChnlNum - interleave phy number (< 0 - not selected)
    
  Output Value: none
	
	Return Value: none
************************************************************************
*/
void BmeNIconfigCh(unsigned int portNum, int fastChnlNum, int ilvChnlNum)
{
	if (fastChnlNum >= 0)
	{
		writePIO_SingleRegChannel ((int *) TNICH_FAST, portNum, (fastChnlNum << 25));

		if (fastChnlNum < ATM_MAX_PORT)
		{
			writePIO_SingleRegChannel ((int *) TNIPHY_LOW, fastChnlNum, 0x80000000+ (portNum<<26));
			writePIO_SingleRegChannel ((int *) TNIPHY_LOW_ONOFF, fastChnlNum, 0);
		}
		else
		{
			writePIO_SingleRegChannel ((int *) TNIPHY_HIGH, fastChnlNum -ATM_MAX_PORT, 0x80000000+(portNum<<26));
			writePIO_SingleRegChannel ((int *) TNIPHY_HIGH_ONOFF, fastChnlNum -ATM_MAX_PORT, 0);
		}
    // X FIFO    
    writePIO_SingleRegChannel ((int *)XFIFOF_CXFT_A, portNum ,  0x2d);
    writePIO_SingleRegChannel ((int *)XFIFOI_CXFT_A, portNum ,  0x2c);

    // C FIFO
    writePIO_SingleRegChannel ((int *)CCFT0_A, portNum ,  0x2b);
    writePIO_SingleRegChannel ((int *)CCFT1_A, portNum ,  0x2a);

		atmPortF2Ni[portNum] = fastChnlNum;
	}
	else
		atmPortF2Ni[portNum] = ATM_PORT_NOT_USED;
  
	if (ilvChnlNum >= 0)
	{
		writePIO_SingleRegChannel ((int *) TNICH_INLV, portNum, (ilvChnlNum << 25));

		if (ilvChnlNum < ATM_MAX_PORT)
		{
			writePIO_SingleRegChannel ((int *) TNIPHY_LOW, ilvChnlNum, portNum<<26);
			writePIO_SingleRegChannel ((int *) TNIPHY_LOW_ONOFF, ilvChnlNum, 0);
		}
		else
		{
			ilvChnlNum -= ATM_MAX_PORT;
			writePIO_SingleRegChannel ((int *) TNIPHY_HIGH, ilvChnlNum -ATM_MAX_PORT, portNum<<26);
			writePIO_SingleRegChannel ((int *) TNIPHY_HIGH_ONOFF, ilvChnlNum -ATM_MAX_PORT, 0);
		}

    writePIO_SingleRegChannel ((int *)XFIFOF_CXFT_A, portNum ,  0x2c);
    writePIO_SingleRegChannel ((int *)XFIFOI_CXFT_A, portNum ,  0x2d);

    writePIO_SingleRegChannel ((int *)CCFT0_A, portNum ,  0x2a);
    writePIO_SingleRegChannel ((int *)CCFT1_A, portNum ,  0x2b);

		atmPortI2Ni[portNum] = ilvChnlNum;
	}
	else
		atmPortI2Ni[portNum] = ATM_PORT_NOT_USED;


// JENO DEBUG TNI config also enables
#if 1
	BmeNIenableCh2(portNum);

	// Reset R/W pointers Must be like this to jump start TNI
	writePIO_SingleRegChannel ((int *)XFIFOF_CXFT_B, portNum ,  0);
	writePIO_SingleRegChannel ((int *)XFIFOI_CXFT_B, portNum ,  0);

	// Reset R/W pointers Must be like this to jump start TNI
	writePIO_SingleRegChannel ((int *)CCFT0_B, portNum ,  0);
	writePIO_SingleRegChannel ((int *)CCFT1_B, portNum ,  0);

#endif
}


/*
************************************************************************
	Function: BmeNIenableCh
	
	Description: Enable network interface channel.  This function will
               not validate the input parameters.
    
  Input Value: fastChnlNum - fast path phy number (< 0 - not selected)
               ilvChnlNum - interleave phy number (< 0 - not selected)
    
  Output Value: none
	
	Return Value: none
************************************************************************
*/
// JENO DEBUG Remove the TNI enable function
void BmeNIenableCh(u8 port)
#if 1
{}
void BmeNIenableCh2(u8 port)
#endif
{
	u32 fastUtopia, ilvUtopia;

	/* Get Utopia Ch num */
	fastUtopia = atmPortF2Ni[port];
	ilvUtopia  = atmPortI2Ni[port];

	if( fastUtopia != ATM_PORT_NOT_USED) {
		/* TNI */
		writePIO_SingleRegChannel((int*) TNICH_FAST, port, 0x80000000 + (u32) (fastUtopia << 25));

		if ( fastUtopia< ATM_MAX_PORT)
			writePIO_SingleRegChannel ((int *) TNIPHY_LOW_ONOFF, fastUtopia, 0x80000000);
		else
			writePIO_SingleRegChannel ((int *) TNIPHY_HIGH_ONOFF, fastUtopia -ATM_MAX_PORT, 0x80000000);

		/* RNI */
		if ( fastUtopia< ATM_MAX_PORT)
			writePIO_SingleRegChannel ((int *) PHY_CTRL_A, fastUtopia, 0x80000000);
		else
			writePIO_SingleRegChannel ((int *) PHY_CTRL_B, fastUtopia -ATM_MAX_PORT, 0x80000000);

	}

	if( ilvUtopia != ATM_PORT_NOT_USED) {
		/* TNI */
		writePIO_SingleRegChannel((int*) TNICH_INLV, port, 0x80000000 + (u32) (ilvUtopia << 25));

		if (ilvUtopia < ATM_MAX_PORT)
			writePIO_SingleRegChannel ((int *) TNIPHY_LOW_ONOFF, ilvUtopia, 0x80000000);
		else
			writePIO_SingleRegChannel ((int *) TNIPHY_HIGH_ONOFF, ilvUtopia - ATM_MAX_PORT, 0x80000000);

		/* RNI */
		if (ilvUtopia < ATM_MAX_PORT)
			writePIO_SingleRegChannel ((int *) PHY_CTRL_A, ilvUtopia, 0x80000000);
		else
			writePIO_SingleRegChannel ((int *) PHY_CTRL_B, ilvUtopia - ATM_MAX_PORT, 0x80000000);
	}
}


/*
************************************************************************
	Function: BmeNIdisableCh
	
	Description: Disable network interface channel.  This function will
               not validate the input parameters.
    
  Input Value: fastChnlNum - fast path phy number (< 0 - not selected)
               ilvChnlNum - interleave phy number (< 0 - not selected)
    
  Output Value: none
	
	Return Value: none
************************************************************************
*/
void BmeNIdisableCh(u8 port)
#if 1  // JENO DEBUG No DISABLE of TNI
{
}
#else
{
	u32 fastUtopia, ilvUtopia;

	/* Get Utopia Ch num */
	fastUtopia = atmPortF2Ni[port];
	ilvUtopia  = atmPortI2Ni[port];

	if( fastUtopia != ATM_PORT_NOT_USED) {
		/* TNI */
		if ( fastUtopia< ATM_MAX_PORT)
			writePIO_SingleRegChannel ((int *) TNIPHY_LOW_ONOFF, fastUtopia, 0);
		else
			writePIO_SingleRegChannel ((int *) TNIPHY_HIGH_ONOFF, fastUtopia -ATM_MAX_PORT, 0);

		writePIO_SingleRegChannel((int*) TNICH_FAST, port, (fastUtopia << 25));
	
//JENO1 we won't disable RNI
#if 0
		/* RNI */
		if ( fastUtopia< ATM_MAX_PORT)
			writePIO_SingleRegChannel ((int *) PHY_CTRL_A, fastUtopia, 0);
		else
			writePIO_SingleRegChannel ((int *) PHY_CTRL_B, fastUtopia -ATM_MAX_PORT, 0);
#endif
	}


	if( ilvUtopia != ATM_PORT_NOT_USED) {
		/* TNI */
		if (ilvUtopia < ATM_MAX_PORT)
			writePIO_SingleRegChannel ((int *) TNIPHY_LOW_ONOFF, ilvUtopia, 0);
		else
			writePIO_SingleRegChannel ((int *) TNIPHY_HIGH_ONOFF, ilvUtopia - ATM_MAX_PORT, 0);

		writePIO_SingleRegChannel((int*) TNICH_INLV, port, (ilvUtopia << 25));
	
//JENO1 we won't disable RNI
#if 0
		/* RNI */
		if (ilvUtopia < ATM_MAX_PORT)
			writePIO_SingleRegChannel ((int *) PHY_CTRL_A, ilvUtopia, 0);
		else
			writePIO_SingleRegChannel ((int *) PHY_CTRL_B, ilvUtopia - ATM_MAX_PORT, 0);
#endif
	}
}

#endif

/*
************************************************************************
	Function: BmeNIdisableCh
	
	Description: Disable network interface channel.  This function will
               not validate the input parameters.
    
  Input Value: fastChnlNum - fast path phy number (< 0 - not selected)
               ilvChnlNum - interleave phy number (< 0 - not selected)
    
  Output Value: none
	
	Return Value: none
************************************************************************
*/
void BmeNIdestroyCh(u8 port)
{
	u32 fastUtopia, ilvUtopia;
	int iChNum, iUtopiaAddr;

	iChNum      = (31 << 26);
	iUtopiaAddr = (63 << 25);

	/* Get Utopia Ch num */
	fastUtopia = atmPortF2Ni[port];
	ilvUtopia  = atmPortI2Ni[port];

	if( fastUtopia != ATM_PORT_NOT_USED) {
		/* TNI */
		if ( fastUtopia< ATM_MAX_PORT)
		{
			writePIO_SingleRegChannel ((int *) TNIPHY_LOW_ONOFF, fastUtopia, 0);
			writePIO_SingleRegChannel ((int *) TNIPHY_LOW, fastUtopia, iChNum);
		}
		else
		{
			writePIO_SingleRegChannel ((int *) TNIPHY_HIGH_ONOFF, fastUtopia -ATM_MAX_PORT, 0);
			writePIO_SingleRegChannel ((int *) TNIPHY_HIGH, fastUtopia -ATM_MAX_PORT, iChNum);
		}

		writePIO_SingleRegChannel((int*) TNICH_FAST, port, iUtopiaAddr);
	
		/* RNI */
		if ( fastUtopia< ATM_MAX_PORT)
			writePIO_SingleRegChannel ((int *) PHY_CTRL_A, fastUtopia, 0);
		else
			writePIO_SingleRegChannel ((int *) PHY_CTRL_B, fastUtopia -ATM_MAX_PORT, 0);

		atmPortF2Ni[port] = ATM_PORT_NOT_USED;
	}


	if( ilvUtopia != ATM_PORT_NOT_USED) {
		/* TNI */
		if (ilvUtopia < ATM_MAX_PORT)
		{
			writePIO_SingleRegChannel ((int *) TNIPHY_LOW_ONOFF, ilvUtopia, 0);
			writePIO_SingleRegChannel ((int *) TNIPHY_LOW, ilvUtopia, iChNum);
		}
		else
		{
			writePIO_SingleRegChannel ((int *) TNIPHY_HIGH_ONOFF, ilvUtopia - ATM_MAX_PORT, 0);
			writePIO_SingleRegChannel ((int *) TNIPHY_HIGH, ilvUtopia - ATM_MAX_PORT, iChNum);
		}

		writePIO_SingleRegChannel((int*) TNICH_INLV, port, iUtopiaAddr);
	
		/* RNI */
		if (ilvUtopia < ATM_MAX_PORT)
			writePIO_SingleRegChannel ((int *) PHY_CTRL_A, ilvUtopia, 0);
		else
			writePIO_SingleRegChannel ((int *) PHY_CTRL_B, ilvUtopia - ATM_MAX_PORT, 0);
	
		atmPortI2Ni[port] = ATM_PORT_NOT_USED;
	}
}



/*
************************************************************************
	Function: BmeNI_Check ATM Stats
	
	Description: check to ss if ATM is locked
    
    Input Value: Port number
    
	Return Value: 
		1- Locked
		0- Not Locked

************************************************************************
*/
int BmeNIcheckAtmState (u8 port)
{
 u32 usAtmState, utopiaPort;
 int iOffset, iRet;

   	iRet = 0;

	utopiaPort = atmPortF2Ni[port];
	if ( utopiaPort != ATM_PORT_NOT_USED )
	{
		iOffset = ATM_STATE_OFFSET + 0x40*((int) port) + 12;

		usAtmState = readPIO_SingleRegChannel((int *)(ADDRESS_DEMAPPERCPU_DCACHE_PIO+iOffset), 0);

		if ( usAtmState & 0x400000 )
		{
//			eventLog ("Fast Path: ATM intf is locked port %d", port);
			iRet |= FAST_PATH_LOCKED;
		}
		else
    {
    }
//			eventLog ("Fast path: ATM intf is NOT locked port %d", port);
	}

	utopiaPort = atmPortI2Ni[port];
	if ( utopiaPort != ATM_PORT_NOT_USED )
	{
		iOffset = ATM_STATE_OFFSET + 0x40*((int) port) + 44;

		usAtmState = readPIO_SingleRegChannel((int *)(ADDRESS_DEMAPPERCPU_DCACHE_PIO+iOffset), 0);
	
		if ( usAtmState & 0x400000 )
		{
//			eventLog ("Inlv Path: ATM intf is locked port %d", port);
			iRet |= INLV_PATH_LOCKED;
		}
		else
    {
    }
//			eventLog ("Inlv path: ATM intf is NOT locked port %d", port);
	}

	return (iRet);
}



/*
************************************************************************
	Function: BmeNI_GetCh2Fast
	
	Description: Gives NI chanel corresponding to Fast port given
    
    Input Value: Port number
    
	Return Value: NI channel

************************************************************************
*/
u8 BmeNI_GetCh2Fast(u8 port)
{
	return atmPortF2Ni[port];
}
	

/*
************************************************************************
	Function: BmeNI_GetCh2Intlv
	
	Description: Gives NI chanel corresponding to Fast port given
    
    Input Value: Port number
    
	Return Value: NI channel

************************************************************************
*/
u8 BmeNI_GetCh2Intlv(u8 port)
{
	return atmPortI2Ni[port];
}


/*
************************************************************************
	Function: BmeNI_ClearCFIFO
	
	Description: Clear CFIFO for the fast and interleave channels
    
    Input Value: Port number
    
	Return Value: None

************************************************************************
*/
void BmeNI_ClearCFIFO(u8 port)
{
	int uCh, bank, reg;

	/* Clean Fast Utopia ch Cfifo */
	uCh = atmPortF2Ni[port];
	bank = uCh & 1;
	reg = uCh >> 1;
	if(uCh != ATM_PORT_NOT_USED){
		if(bank)
			writePIO_SingleRegChannel((int *)CCFT1_B, reg, 0x0);	
		else
			writePIO_SingleRegChannel((int *)CCFT0_B, reg, 0x0);				
	}


	/* Clean Interleave Utopia ch Cfifo */
	uCh = atmPortI2Ni[port];
	bank = uCh & 1;
	reg = uCh >> 1;
	if(uCh != ATM_PORT_NOT_USED){
		if(bank)
			writePIO_SingleRegChannel((int *)CCFT1_B, reg, 0x0);	
		else
			writePIO_SingleRegChannel((int *)CCFT0_B, reg, 0x0);				
	}
}


