#include <stdio.h>
#include <errno.h>
#include <string.h>
#include "dagapi.h"
#include "dag_config.h"
#include "dag_component.h"
#include "dag_platform.h"
#include "dagutil.h"
#include "dagapi.h"
#include "dag_config.h"
#include "dag_component.h"
#include "dag_platform.h"
#include "dagutil.h"
#include "bfs_lib.h"

#define MAX_ATTEMPTS 100

/**
 *  * Writes an entry into the BFS cam 
 *  *
 *  * @param[in]  header     The structure which contains the F/W interface
 *  * 
 *  * @param[in]  addr       The address (index) of the TCAM entry to write.
 *  *
 *  * @param[in]  data       Pointer to an array of bytes that gets loaded
 *  *                        into the data part of the entry.
 *  * @param[in]  mask       Pointer to an array of bytes that gets loaded
 *  *                        into the mask part of the entry.
 *  * @param[in]  db         The database (BANK into which the data is to be written.)

 *  * @return                Returns one of the following error codes.
 *  * @retval EINVAL         An invalid argument was supplied
 *  * @retval ETIMEDOUT      Timedout waiting for the chip to indicate the reading
 *  *                        procedure was complete.
 *  * @retval ESUCCESS       The data and mask in the tcam at the given address is as expected.
 *  */
int
write_bfscam_value(BFSStateHeaderPtr header,uint32_t db ,uint32_t address, uint32_t data[13],uint32_t mask[13])
{
	int index = 0;
	volatile unsigned temp = 0;
	int attempts = 0;
	bool inactive_bank = false;
	bool bank = false;
	
	
	/* Sanity checking */
	if ( header == NULL )
		return EINVAL;
	if ( address > MAX_BFS_POSSIBLE_RULES)
		return EINVAL;
	if ( data == NULL )
		return EINVAL;
	if ( mask == NULL )
		return EINVAL;
	if( db > 1)
		return EINVAL;

	/*If new interface call the generic function.*/
	if (header->version == 1)
	{
		/*call the new function.*/
		write_bfscam_value_generic(header,db ,address,data,mask);
		return ESUCCESS;
	}

	if((db & 0x1) == 0)
		bank = false;
	else if((db & 0x1) == 1)
		bank = true;

	inactive_bank = get_inactive_bank(header);

	if(bank != inactive_bank)
	{
		dagutil_warning("Trying to program to the active bank.The the TCAM will not be programmed.\n");
		return EINVAL;
	}

	
    


	dagutil_verbose_level(3,"write_bfscam_value  bptr %p database %d address %d \n",header->bfs_register_base,db,address);	
	/*Word index 1*/

	dagutil_verbose_level(3,"DATA 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x \n",data[0],data[1],data[2],data[3],data[4],data[5],data[6],data[7],data[8],data[9],
data[10],data[11],data[12]);
	
	dagutil_verbose_level(3,"MASK 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x \n",mask[0],mask[1],mask[2],mask[3],mask[4],mask[5],mask[6],mask[7],mask[8],mask[9],	mask[10],mask[11],mask[12]);
	
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_ADDRESS_REGISTER) = ((address << 16) | (0x00000000));

	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_DATA_IN) = (data[0] & 0x3fffffff );
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_MASK_IN) = (mask[0] & 0x3fffffff );

	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = ((BIT31) | (bank << 29) | (index << 1));

	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
	
	while (((temp & BIT0) != 1) && (attempts <  MAX_ATTEMPTS))
	{
		temp = 	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
		attempts++;
	}
	if(attempts == MAX_ATTEMPTS)
	{
		dagutil_warning("timeout in %s\n", __FUNCTION__);
		return ETIMEDOUT;
	}
	
	index++;
	/*Word index 2*/
	
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_DATA_IN) =(((data[0] & new_base_msb_mask_2) >> 30 )|((data[1] &  lsb_mask_28 ) << 2 ));
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_MASK_IN) =(((mask[0] & new_base_msb_mask_2) >> 30 )|((mask[1] &  lsb_mask_28 ) << 2 ));

	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = ((BIT31) | (bank << 29) | (index << 1));

	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
	
	while (((temp & BIT0) != 1) && (attempts <  MAX_ATTEMPTS))
	{
		temp = 	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
		attempts++;
	}
	if(attempts == MAX_ATTEMPTS)
	{
		dagutil_warning("timeout in %s\n", __FUNCTION__);
		return ETIMEDOUT;
	}
	index++;
	
	/*word index 3 */
	
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_DATA_IN) =(((data[1] & new_base_msb_mask_4) >> 28 )|((data[2] &  lsb_mask_26) << 4 ));
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_MASK_IN) =(((mask[1] & new_base_msb_mask_4) >> 28 )|((mask[2] &  lsb_mask_26) << 4 ));

	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = ((BIT31) | (bank << 29) | (index << 1));

	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
	while (((temp & BIT0)!= 1) && (attempts <  MAX_ATTEMPTS))
	{
		temp = 	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
		attempts++;
	}
	if(attempts == MAX_ATTEMPTS)
	{
		dagutil_warning("timeout in %s\n", __FUNCTION__);
		return ETIMEDOUT;
	}
	index++;

	
	/*word index 4*/
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_DATA_IN) = (((data[2] & new_base_msb_mask_6)  >> 26 )|((data[3]  & lsb_mask_24)  << 6 ));
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_MASK_IN) = (((mask[2] & new_base_msb_mask_6)  >> 26 )|((mask[3]  & lsb_mask_24)  << 6 ));

	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = ((BIT31) | (bank << 29) | (index << 1));

	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
	while (((temp & BIT0)!= 1) && (attempts <  MAX_ATTEMPTS))
	{
		temp = 	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
		attempts++;
	}
	if(attempts == MAX_ATTEMPTS)
	{
		dagutil_warning("timeout in %s\n", __FUNCTION__);
		return ETIMEDOUT;
	}
	index++;
	
		
	/*word index 5*/
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_DATA_IN) = (((data[3] & new_base_msb_mask_8)  >> 24 )|((data[4] &  lsb_mask_22 << 8)));
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_MASK_IN) = (((mask[3] & new_base_msb_mask_8)  >> 24 )|((mask[4] &  lsb_mask_22 << 8)));

	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = ((BIT31) | (bank << 29) | (index << 1));

	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
	while (((temp & BIT0)!= 1) && (attempts <  MAX_ATTEMPTS))
	{
		temp = 	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
		attempts++;
	}
	if(attempts == MAX_ATTEMPTS)
	{
		dagutil_warning("timeout in %s\n", __FUNCTION__);
		return ETIMEDOUT;
	}
	index++;

	
	
	/*word index 6*/
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_DATA_IN) = (((data[4] & new_base_msb_mask_10)  >> 22 ) | ((data[5] & lsb_mask_20 << 10)));
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_MASK_IN) = (((mask[4] & new_base_msb_mask_10)  >> 22 ) | ((mask[5] & lsb_mask_20 << 10)));

	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = ((BIT31) | (bank << 29) | (index << 1));

	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
	
	while (((temp & BIT0) != 1) && (attempts <  MAX_ATTEMPTS))
	{
		temp = 	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
		attempts++;
	}
	if(attempts == MAX_ATTEMPTS)
	{
		dagutil_warning("timeout in %s\n", __FUNCTION__);
		return ETIMEDOUT;
	}
	index++;
	
	
	
	/*word index 7*/
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_DATA_IN) = (((data[5] & new_base_msb_mask_12) >> 20 )|((data[6] & lsb_mask_18) <<  12 ));
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_MASK_IN) = (((mask[5] & new_base_msb_mask_12) >> 20 )|((mask[6] & lsb_mask_18) <<  12 ));

	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = ((BIT31) | (bank << 29) | (index << 1));

	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);

	while (((temp & BIT0)!= 1) && (attempts <  MAX_ATTEMPTS))
	{
		temp = 	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
		attempts++;
	}
	if(attempts == MAX_ATTEMPTS)
	{
		dagutil_warning("timeout in %s\n", __FUNCTION__);
		return ETIMEDOUT;
	}
	index++;
	
	/*word index 8*/
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_DATA_IN) = (((data[6] & new_base_msb_mask_14) >> 18 )|((data[7] & lsb_mask_16) <<  14 ));
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_MASK_IN) = (((mask[6] & new_base_msb_mask_14) >> 18 )|((mask[7] & lsb_mask_16) <<  14 ));

	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = ((BIT31) | (bank << 29) | (index << 1));

	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
	while (((temp & BIT0)!= 1) && (attempts <  MAX_ATTEMPTS))
	{
		temp = 	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
		attempts++;
	}
	if(attempts == MAX_ATTEMPTS)
	{
		dagutil_warning("timeout in %s\n", __FUNCTION__);
		return ETIMEDOUT;
	}
	index++;
	
	/*word index 9*/
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_DATA_IN) = (((data[7] & new_base_msb_mask_16) >> 16 )|((data[8] & lsb_mask_14 ) <<  16 ));
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_MASK_IN) = (((mask[7] & new_base_msb_mask_16) >> 16 )|((mask[8] & lsb_mask_14 ) <<  16 ));

	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = ((BIT31) | (bank << 29) | (index << 1));

	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
	while (((temp & BIT0) != 1) && (attempts <  MAX_ATTEMPTS))
	{
		temp = 	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
		attempts++;
	}
	if(attempts == MAX_ATTEMPTS)
	{
		dagutil_warning("timeout in %s\n", __FUNCTION__);
		return ETIMEDOUT;
	}
	index++;
	
	
	/*word index 10*/
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_DATA_IN) =(((data[8] & new_base_msb_mask_18) >> 14)|((data[9] & lsb_mask_12)  <<  18 ));
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_MASK_IN) =(((mask[8] & new_base_msb_mask_18) >> 14)|((mask[9] & lsb_mask_12)  <<  18 ));

	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = ((BIT31) | (bank << 29) | (index << 1));

	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
	while (((temp & BIT0) != 1) && (attempts <  MAX_ATTEMPTS))
	{
		temp = 	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
		attempts++;
	}
	if(attempts == MAX_ATTEMPTS)
	{
		dagutil_warning("timeout in %s\n", __FUNCTION__);
		return ETIMEDOUT;
	}
	index++;
	
	
	
	/*word index 11*/
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_DATA_IN) =(((data[9] & new_base_msb_mask_20)>> 12) |((data[10] & lsb_mask_10 )  <<  20 ));
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_MASK_IN) =(((mask[9] & new_base_msb_mask_20)>> 12) |((mask[10] & lsb_mask_10 )  <<  20 ));

	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = ((BIT31) | (bank << 29) | (index << 1));

	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
	while (((temp & BIT0)!= 1) && (attempts <  MAX_ATTEMPTS))
	{
		temp = 	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
		attempts++;
	}
	if(attempts == MAX_ATTEMPTS)
	{
		dagutil_warning("timeout in %s\n", __FUNCTION__);
		return ETIMEDOUT;
	}
	index++;
	
		

	/*word index 12*/
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_DATA_IN) = (((data[10]  & new_base_msb_mask_22)  >> 10)|((data[11] & lsb_mask_8 )  <<  22));
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_MASK_IN) = (((mask[10]  & new_base_msb_mask_22)  >> 10)|((mask[11] & lsb_mask_8 )  <<  22));

	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = ((BIT31) | (bank << 29) | (index << 1));

	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
	while (((temp & BIT0)!= 1) && (attempts <  MAX_ATTEMPTS))
	{
		temp = 	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
		attempts++;
	}
	if(attempts == MAX_ATTEMPTS)
	{
		dagutil_warning("timeout in %s\n", __FUNCTION__);
		return ETIMEDOUT;
	}
	index++;

	
	
	/*word index 13*/
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_DATA_IN) = (((data[11] & new_base_msb_mask_24) >> 8)|((data[12] & lsb_mask_6) <<   24));
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_MASK_IN) = (((mask[11] & new_base_msb_mask_24) >> 8)|((mask[12] & lsb_mask_6) <<   24));  

	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = ((BIT31) | (bank << 29) | (index << 1));

	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
	while(((temp & BIT0)!= 1) && (attempts <  MAX_ATTEMPTS))
	{
		temp = 	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
		attempts++;
	}
	if(attempts == MAX_ATTEMPTS)
	{
		dagutil_warning("timeout in %s\n", __FUNCTION__);
		return ETIMEDOUT;
	}
	return ESUCCESS;
}
/**
 *  * Writes an entry into the BFS cam 
 *  *
 *  * @param[in]  header     The structure which contains the F/W interface
 *  * 
 *  * @param[in]  addr       The address (index) of the TCAM entry to write.
 *  *
 *  * @param[in]  data       Pointer to an array of bytes that gets loaded
 *  *                        into the data part of the entry.
 *  * @param[in]  mask       Pointer to an array of bytes that gets loaded
 *  *                        into the mask part of the entry.
 *  * @param[in]  db         The database (BANK into which the data is to be written.)

 *  * @return                Returns one of the following error codes.
 *  * @retval EINVAL         An invalid argument was supplied
 *  * @retval ETIMEDOUT      Timedout waiting for the chip to indicate the reading
 *  *                        procedure was complete.
 *  * @retval ESUCCESS       The data and mask in the tcam at the given address is as expected.
 *  */
int
write_bfscam_value_generic(BFSStateHeaderPtr header,uint32_t db ,uint32_t address, uint32_t data[13],uint32_t mask[13])
{
	volatile unsigned temp = 0;
	int attempts = 0;
	bool inactive_bank = false;
	bool bank = false; 
	int loop = 0;
	
	/* Sanity checking */
	if ( header == NULL )
		return EINVAL;
	if ( address > MAX_BFS_POSSIBLE_RULES)
		return EINVAL;
	if ( data == NULL )
		return EINVAL;
	if ( mask == NULL )
		return EINVAL;
	if( db > 1)
		return EINVAL;

	if((db & 0x1) == 0)
		bank = false;
	else if((db & 0x1) == 1)
		bank = true;

	inactive_bank = get_inactive_bank(header);

	if(bank != inactive_bank)
	{
		dagutil_warning("trying to program to the active bank.will not be programmed.");
		return EINVAL;
	}
	dagutil_verbose_level(3,"write_bfscam_value  bptr %p database %d address %d \n",header->bfs_register_base,db,address);	
	/*Word index 1*/

	dagutil_verbose_level(3,"DATA 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x \n",data[0],data[1],data[2],data[3],data[4],data[5],data[6],data[7],data[8],data[9],data[10],data[11],data[12]);
	
	dagutil_verbose_level(3,"MASK 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x \n",mask[0],mask[1],mask[2],mask[3],mask[4],mask[5],mask[6],mask[7],mask[8],mask[9],mask[10],mask[11],mask[12]);

	 
	 *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = (BIT1);

	/*write the rule number.*/
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_ADDRESS_REGISTER) = ((address << 16) | (0x00000000));

	/*Write the bit corrosponding to the bank you want to program.*/
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = (bank << 29);
	
	/*write the rule write enable bit.*/
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = (BIT31);

	for (loop = 0; loop <= BFS_RULE_WIDTH/32 ; loop++)
	{                                                                                           
	                                                                                           
			*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_DATA_IN) = data[loop];
			*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_MASK_IN) = mask[loop];
	
			dagutil_verbose("rule number [%d]:data[%d] 0x%.8x mask[%d] 0x%.8x \n",address,loop,data[loop],loop,mask[loop]);

    		/*write data or mask ready bit.*/	                                                                                           
    		*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = (BIT3);	                                                                                           	
	}
    /*Wait till the rule operation completed bit is set.*/	                                                                                           
	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
	while(((temp & BIT0)!= 1) && (attempts <  MAX_ATTEMPTS))
	{
		temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
		dagutil_nanosleep(2000);
		attempts++;
	}
	if(attempts == MAX_ATTEMPTS)
	{
		dagutil_warning("timeout in %s\n", __FUNCTION__);
		return ETIMEDOUT;
	}
	return ESUCCESS;
}

/**
 *  * Verifies if an entry in the TCAM at the given address is correct.
 *  *
 *  * @param[in]  header     The structure which contains the F/W interface
 *  * 
 *  * @param[in]  addr       The address (index) of the TCAM entry to write.
 *  *
 *  * @param[in]  data       Pointer to an array of bytes that gets loaded
 *  *                        into the data part of the entry.
 *  * @param[in]  mask       Pointer to an array of bytes that gets loaded
 *  *                        into the mask part of the entry.
 *  * @param[in]  db         The database (BANK into which the data is to be written.)

 *  * @return                Returns one of the following error codes.
 *  * @retval EINVAL         An invalid argument was supplied
 *  * @retval ETIMEDOUT      Timedout waiting for the chip to indicate the reading
 *  *                        procedure was complete.
 *  * @retval ESUCCESS       The data and mask in the tcam at the given address is as expected.
 *  * @retval ENOMATCH       The data and mask in the tcam at the given address is not as expected.
 *  */
int
read_verify_bfscam_value(BFSStateHeaderPtr header,uint32_t db ,uint32_t address, uint32_t data[13],uint32_t mask[13])
{
	int index = 0;
	volatile unsigned temp = 0;
	int attempts = 0;
	//bool read_match = false;
	bool inactive_bank = false;
	bool bank = false; 
	
	/* Sanity checking */
	if ( header == NULL )
		return EINVAL;
	if ( address > MAX_BFS_POSSIBLE_RULES)
		return EINVAL;
	if ( data == NULL )
		return EINVAL;
	if ( mask == NULL )
		return EINVAL;
	if( db > 1)
		return EINVAL;


	if((db & 0x1) == 0)
		bank = false;
	else if((db & 0x1) == 1)
		bank = true;

	inactive_bank = get_inactive_bank(header);

	if(bank != inactive_bank)
	{
		dagutil_warning("trying to program to the active bank.will not be programmed.");
		return EINVAL;
	}
	dagutil_verbose_level(3,"write_bfscam_value  bptr %p database %d address %d \n",header->bfs_register_base,db,address);	
	/*Word index 1*/

	dagutil_verbose_level(3,"DATA 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x \n",data[0],data[1],data[2],data[3],data[4],data[5],data[6],data[7],data[8],data[9],
	data[10],data[11],data[12]);
	
	dagutil_verbose_level(3,"MASK 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x \n",mask[0],mask[1],mask[2],mask[3],mask[4],mask[5],mask[6],mask[7],mask[8],mask[9],	mask[10],mask[11],mask[12]);
	
	
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_ADDRESS_REGISTER) = (address << 16) | (0x00000000);

	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_DATA_IN) = (data[0] & 0x3fffffff);
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_MASK_IN) = (mask[0] & 0x3fffffff);

	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = ((BIT30) | (bank << 29) | (index << 1));

	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
	
	while (((temp & BIT0) != 1) && (attempts <  MAX_ATTEMPTS))
	{
		temp = 	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
		attempts++;
	}
	if(attempts == MAX_ATTEMPTS)
	{
		dagutil_warning("timeout in %s\n", __FUNCTION__);
		return ETIMEDOUT;
	}
	
	index++;
	/*Word index 2*/
	
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_DATA_IN) = (((data[0] & new_base_msb_mask_2) >> 30 )|((data[1] &  lsb_mask_28 ) << 2 ));
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_MASK_IN) = (((mask[0] & new_base_msb_mask_2) >> 30 )|((mask[1] &  lsb_mask_28 ) << 2 ));

	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = ((BIT30) | (bank << 29) | (index << 1));

	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
	
	while (((temp & BIT0) != 1) && (attempts <  MAX_ATTEMPTS))
	{
		temp = 	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
		attempts++;
	}
	if(attempts == MAX_ATTEMPTS)
	{
		dagutil_warning("timeout in %s\n", __FUNCTION__);
		return ETIMEDOUT;
	}
	index++;
	
	/*word index 3 */
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_DATA_IN) = (((data[1] & new_base_msb_mask_4) >> 28 )|((data[2] &  lsb_mask_26) << 4 ));
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_MASK_IN) = (((mask[1] & new_base_msb_mask_4) >> 28 )|((mask[2] &  lsb_mask_26) << 4 ));

	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = ((BIT30) | (bank << 29) | (index << 1));

	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
	while (((temp & BIT0)!= 1) && (attempts <  MAX_ATTEMPTS))
	{
		temp = 	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
		attempts++;
	}
	if(attempts == MAX_ATTEMPTS)
	{
		dagutil_warning("timeout in %s\n", __FUNCTION__);
		return ETIMEDOUT;
	}
	index++;
	
	/*word index 4*/
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_DATA_IN) = (((data[2] & new_base_msb_mask_6)  >> 26 )|((data[3]  & lsb_mask_24)  << 6 ));
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_MASK_IN) = (((mask[2] & new_base_msb_mask_6)  >> 26 )|((mask[3]  & lsb_mask_24)  << 6 ));

	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = ((BIT30) | (bank << 29) | (index << 1));

	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
	while (((temp & BIT0)!= 1) && (attempts <  MAX_ATTEMPTS))
	{
		temp = 	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
		attempts++;
	}
	if(attempts == MAX_ATTEMPTS)
	{
		dagutil_warning("timeout in %s\n", __FUNCTION__);
		return ETIMEDOUT;
	}
	index++;
	
	/*word index 5*/
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_DATA_IN) = (((data[3] & new_base_msb_mask_8)  >> 24 )|((data[4] &  lsb_mask_22 << 8)));
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_MASK_IN) = (((mask[3] & new_base_msb_mask_8)  >> 24 )|((mask[4] &  lsb_mask_22 << 8)));

	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = ((BIT30) | (bank << 29) | (index << 1));

	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
	while (((temp & BIT0)!= 1) && (attempts <  MAX_ATTEMPTS))
	{
		temp = 	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
		attempts++;
	}
	if(attempts == MAX_ATTEMPTS)
	{
		dagutil_warning("timeout in %s\n", __FUNCTION__);
		return ETIMEDOUT;
	}
	index++;
	
	/*word index 6*/
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_DATA_IN) = (((data[4] & new_base_msb_mask_10)  >> 22 ) | ((data[5] & lsb_mask_20 << 10)));
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_MASK_IN) = (((mask[4] & new_base_msb_mask_10)  >> 22 ) | ((data[5] & lsb_mask_20 << 10)));

	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = ((BIT30) | (bank << 29) | (index << 1));

	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
	
	while (((temp & BIT0) != 1) && (attempts <  MAX_ATTEMPTS))
	{
		temp = 	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
		attempts++;
	}
	if(attempts == MAX_ATTEMPTS)
	{
		dagutil_warning("timeout in %s\n", __FUNCTION__);
		return ETIMEDOUT;
	}
	index++;
	
	/*word index 7*/
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_DATA_IN) = (((data[5] & new_base_msb_mask_12) >> 20 )|((data[6] & lsb_mask_18) <<  12 ));
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_MASK_IN) = (((mask[5] & new_base_msb_mask_12) >> 20 )|((mask[6] & lsb_mask_18) <<  12 ));

	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = ((BIT30) | (bank << 29) | (index << 1));

	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);

	while (((temp & BIT0)!= 1) && (attempts <  MAX_ATTEMPTS))
	{
		temp = 	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
		attempts++;
	}
	if(attempts == MAX_ATTEMPTS)
	{
		dagutil_warning("timeout in %s\n", __FUNCTION__);
		return ETIMEDOUT;
	}
	index++;
	
	/*word index 8*/
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_DATA_IN) = (((data[6] & new_base_msb_mask_14) >> 18 )|((data[7] & lsb_mask_16) <<  14 ));
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_MASK_IN) = (((mask[6] & new_base_msb_mask_14) >> 18 )|((mask[7] & lsb_mask_16) <<  14 ));

	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = ((BIT30) | (bank << 29) | (index << 1));

	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
	while (((temp & BIT0)!= 1) && (attempts <  MAX_ATTEMPTS))
	{
		temp = 	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
		attempts++;
	}
	if(attempts == MAX_ATTEMPTS)
	{
		dagutil_warning("timeout in %s\n", __FUNCTION__);
		return ETIMEDOUT;
	}
	index++;
	
	/*word index 9*/
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_DATA_IN) = (((data[7] & new_base_msb_mask_16) >> 16 )|((data[8] & lsb_mask_14 ) <<  16 ));
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_MASK_IN) = (((mask[7] & new_base_msb_mask_16) >> 16 )|((mask[8] & lsb_mask_14 ) <<  16 ));

	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = ((BIT30) | (bank << 29) | (index << 1));

	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
	while (((temp & BIT0) != 1) && (attempts <  MAX_ATTEMPTS))
	{
		temp = 	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
		attempts++;
	}
	if(attempts == MAX_ATTEMPTS)
	{
		dagutil_warning("timeout in %s\n", __FUNCTION__);
		return ETIMEDOUT;
	}
	index++;
	
	/*word index 10*/
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_DATA_IN) =(((data[8] & new_base_msb_mask_18) >> 14)|((data[9] & lsb_mask_12)  <<  18 ));
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_MASK_IN) =(((mask[8] & new_base_msb_mask_18) >> 14)|((mask[9] & lsb_mask_12)  <<  18 ));

	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = ((BIT30) | (bank << 29) | (index << 1));

	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
	while (((temp & BIT0) != 1) && (attempts <  MAX_ATTEMPTS))
	{
		temp = 	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
		attempts++;
	}
	if(attempts == MAX_ATTEMPTS)
	{
		dagutil_warning("timeout in %s\n", __FUNCTION__);
		return ETIMEDOUT;
	}
	index++;
	
	/*word index 11*/
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_DATA_IN) =(((data[9] & new_base_msb_mask_20)>> 12) |((data[10] & lsb_mask_10 )  <<  20 ));
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_MASK_IN) =(((mask[9] & new_base_msb_mask_20)>> 12) |((mask[10] & lsb_mask_10 )  <<  20 ));

	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = ((BIT30) | (bank << 29) | (index << 1));

	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
	while (((temp & BIT0)!= 1) && (attempts <  MAX_ATTEMPTS))
	{
		temp = 	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
		attempts++;
	}
	if(attempts == MAX_ATTEMPTS)
	{
		dagutil_warning("timeout in %s\n", __FUNCTION__);
		return ETIMEDOUT;
	}
	index++;
	
	/*word index 12*/
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_DATA_IN) = (((data[10]  & new_base_msb_mask_22)  >> 10)|((mask[11] & lsb_mask_8 )  <<  22));
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_MASK_IN) = (((mask[10]  & new_base_msb_mask_22)  >> 10)|((mask[11] & lsb_mask_8 )  <<  22));

	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = ((BIT30) | (bank << 29) | (index << 1));

	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
	while (((temp & BIT0)!= 1) && (attempts <  MAX_ATTEMPTS))
	{
		temp = 	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
		attempts++;
	}
	if(attempts == MAX_ATTEMPTS)
	{
		dagutil_warning("timeout in %s\n", __FUNCTION__);
		return ETIMEDOUT;
	}
	index++;
	
	/*word index 13*/
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_DATA_IN) = (((data[11] & new_base_msb_mask_24) >> 8)|((data[12] & lsb_mask_6) <<   24));
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_MASK_IN) = (((mask[11] & new_base_msb_mask_24) >> 8)|((mask[12] & lsb_mask_6) <<   24));  

	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = ((BIT30) | (bank << 29) | (index << 1));

	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
	while (((temp & BIT0)!= 1) && (attempts <  MAX_ATTEMPTS))
	{
		temp = 	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
		attempts++;
	}
	if(attempts == MAX_ATTEMPTS)
	{
		dagutil_warning("timeout in %s\n", __FUNCTION__);
		return ETIMEDOUT;
	}

	/*Check the Program Match Vector*/
	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
	if((((temp & BIT26) >> 26) != 1) && (attempts < MAX_ATTEMPTS))
	{
		temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
		attempts++;
	}
	if(attempts == MAX_ATTEMPTS)
	{
		dagutil_warning("timeout in %s\n", __FUNCTION__);
		return ETIMEDOUT;
	}
	
	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_MATCH_VECTOR);
	if(temp == address)
	{
		dagutil_verbose_level(0,"Tcam Program Match Vector Returned expected index %d\n",temp);
		return ESUCCESS;
	}
	else
	{
		dagutil_verbose_level(0,"Tcam Program Match Vector Returned unexpected index %d\n",temp);	
		return ENOMATCH;
	}
}
/**
 *  * Reads an entry from the BFS cam 
 *  *
 *  * @param[in]  header     The structure which contains the F/W interface
 *  * 
 *  * @param[in]  addr       The address (index) of the TCAM entry to write.
 *  *
 *  * @param[out]  data       Pointer to an array of bytes that gets loaded
 *  *                        into the data part of the entry.
 *  * @param[out]  mask       Pointer to an array of bytes that gets loaded
 *  *                        into the mask part of the entry.
 *  * @param[in]   db        The database (BANK into which the data is to be written.)
 *  *
 *  * @return                Returns one of the following error codes.
 *  * @retval EINVAL         An invalid argument was supplied
 *  * @retval ETIMEDOUT      Timedout waiting for the chip to indicate the reading
 *  *                        procedure was complete.
 *  * @retval ESUCCESS       The data and mask in the tcam at the given address
 *  */
int
read_bfscam_value(BFSStateHeaderPtr header, uint32_t db,uint32_t address, uint32_t data[13],uint32_t mask[13])
{
	int index = 0;
	volatile unsigned temp = 0;
	int attempts = 0;
	bool inactive_bank = false;
	bool bank = false; 
	
	/* Sanity checking */
	if ( header == NULL )
		return EINVAL;
	if ( address > MAX_BFS_POSSIBLE_RULES)
		return EINVAL;
	if ( data == NULL )
		return EINVAL;
	if ( mask == NULL )
		return EINVAL;
	if( db > 1)
		return EINVAL;


	if((db & 0x1) == 0)
		bank = false;
	else if((db & 0x1) == 1)
		bank = true;

	inactive_bank = get_inactive_bank(header);

	if(bank != inactive_bank)
	{
		dagutil_warning("trying to program to the active bank.will not be programmed.");
		return EINVAL;
	}
	dagutil_verbose_level(3,"write_bfscam_value  bptr %p database %d address %d \n",header->bfs_register_base,db,address);	
	/*Word index 1*/

	dagutil_verbose_level(3,"DATA 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x \n",data[0],data[1],data[2],data[3],data[4],data[5],data[6],data[7],data[8],data[9],
data[10],data[11],data[12]);
	
	dagutil_verbose_level(3,"MASK 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x \n",mask[0],mask[1],mask[2],mask[3],mask[4],mask[5],mask[6],mask[7],mask[8],mask[9],	mask[10],mask[11],mask[12]);
	
	
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_ADDRESS_REGISTER) = (address << 16) | (0x00000000);

	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_DATA_IN) = (data[0] & 0x3fffffff);
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_MASK_IN) = (mask[0] & 0x3fffffff);

	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = ((BIT31) | (bank << 29) | (index << 1));

	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
	
	while (((temp & BIT0) != 1) && (attempts <  MAX_ATTEMPTS))
	{
		temp = 	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
		attempts++;
	}
	if(attempts == MAX_ATTEMPTS)
	{
		dagutil_warning("timeout in %s\n", __FUNCTION__);
		return ETIMEDOUT;
	}
	index++;
	/*Word index 2*/
	
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_DATA_IN) = (((data[0] & new_base_msb_mask_2) >> 30 )|((data[1] &  lsb_mask_28 ) << 2 ));
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_MASK_IN) = (((mask[0] & new_base_msb_mask_2) >> 30 )|((mask[1] &  lsb_mask_28 ) << 2 ));

	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = ((BIT31) | (bank << 29) | (index << 1));

	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
	
	while (((temp & BIT0) != 1) && (attempts <  MAX_ATTEMPTS))
	{
		temp = 	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
		attempts++;
	}
	if(attempts == MAX_ATTEMPTS)
	{
		dagutil_warning("timeout in %s\n", __FUNCTION__);
		return ETIMEDOUT;
	}
	index++;
	
	/*word index 3 */
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_DATA_IN) = (((data[1] & new_base_msb_mask_4) >> 28 )|((data[2] &  lsb_mask_26) << 4 ));
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_MASK_IN) = (((mask[1] & new_base_msb_mask_4) >> 28 )|((mask[2] &  lsb_mask_26) << 4 ));

	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = ((BIT31) | (bank << 29) | (index << 1));

	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
	while (((temp & BIT0)!= 1) && (attempts <  MAX_ATTEMPTS))
	{
		temp = 	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
		attempts++;
	}
	if(attempts == MAX_ATTEMPTS)
	{
		dagutil_warning("timeout in %s\n", __FUNCTION__);
		return ETIMEDOUT;
	}
	index++;
	
	/*word index 4*/
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_DATA_IN) = (((data[2] & new_base_msb_mask_6)  >> 26 )|((data[3]  & lsb_mask_24)  << 6 ));
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_MASK_IN) = (((mask[2] & new_base_msb_mask_6)  >> 26 )|((mask[3]  & lsb_mask_24)  << 6 ));

	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = ((BIT31) | (bank << 29) | (index << 1));

	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
	while (((temp & BIT0)!= 1) && (attempts <  MAX_ATTEMPTS))
	{
		temp = 	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
		attempts++;
	}
	if(attempts == MAX_ATTEMPTS)
	{
		dagutil_warning("timeout in %s\n", __FUNCTION__);
		return ETIMEDOUT;
	}
	index++;
	
	/*word index 5*/
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_DATA_IN) = (((data[3] & new_base_msb_mask_8)  >> 24 )|((data[4] &  lsb_mask_22 << 8)));
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_MASK_IN) = (((mask[3] & new_base_msb_mask_8)  >> 24 )|((mask[4] &  lsb_mask_22 << 8)));

	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = ((BIT31) | (bank << 29) | (index << 1));

	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
	while (((temp & BIT0)!= 1) && (attempts <  MAX_ATTEMPTS))
	{
		temp = 	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
		attempts++;
	}
	if(attempts == MAX_ATTEMPTS)
	{
		dagutil_warning("timeout in %s\n", __FUNCTION__);
		return ETIMEDOUT;
	}
	index++;
	
	/*word index 6*/
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_DATA_IN) = (((data[4] & new_base_msb_mask_10)  >> 22 ) | ((data[5] & lsb_mask_20 << 10)));
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_MASK_IN) = (((mask[4] & new_base_msb_mask_10)  >> 22 ) | ((data[5] & lsb_mask_20 << 10)));

	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = ((BIT31) | (bank << 29) | (index << 1));

	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
	
	while (((temp & BIT0) != 1) && (attempts <  MAX_ATTEMPTS))
	{
		temp = 	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
		attempts++;
	}
	if(attempts == MAX_ATTEMPTS)
	{
		dagutil_warning("timeout in %s\n", __FUNCTION__);
		return ETIMEDOUT;
	}
	index++;
	
	/*word index 7*/
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_DATA_IN) = (((data[5] & new_base_msb_mask_12) >> 20 )|((data[6] & lsb_mask_18) <<  12 ));
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_MASK_IN) = (((mask[5] & new_base_msb_mask_12) >> 20 )|((mask[6] & lsb_mask_18) <<  12 ));

	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = ((BIT31) | (bank << 29) | (index << 1));

	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);

	while (((temp & BIT0)!= 1) && (attempts <  MAX_ATTEMPTS))
	{
		temp = 	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
		attempts++;
	}
	if(attempts == MAX_ATTEMPTS)
	{
		dagutil_warning("timeout in %s\n", __FUNCTION__);
		return ETIMEDOUT;
	}
	index++;
	
	/*word index 8*/
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_DATA_IN) = (((data[6] & new_base_msb_mask_14) >> 18 )|((data[7] & lsb_mask_16) <<  14 ));
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_MASK_IN) = (((mask[6] & new_base_msb_mask_14) >> 18 )|((mask[7] & lsb_mask_16) <<  14 ));

	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = ((BIT31) | (bank << 29) | (index << 1));

	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
	while (((temp & BIT0)!= 1) && (attempts <  MAX_ATTEMPTS))
	{
		temp = 	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
		attempts++;
	}
	if(attempts == MAX_ATTEMPTS)
	{
		dagutil_warning("timeout in %s\n", __FUNCTION__);
		return ETIMEDOUT;
	}
	index++;
	
	/*word index 9*/
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_DATA_IN) = (((data[7] & new_base_msb_mask_16) >> 16 )|((data[8] & lsb_mask_14 ) <<  16 ));
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_MASK_IN) = (((mask[7] & new_base_msb_mask_16) >> 16 )|((mask[8] & lsb_mask_14 ) <<  16 ));

	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = ((BIT31) | (bank << 29) | (index << 1));

	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
	while (((temp & BIT0) != 1) && (attempts <  MAX_ATTEMPTS))
	{
		temp = 	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
		attempts++;
	}
	if(attempts == MAX_ATTEMPTS)
	{
		dagutil_warning("timeout in %s\n", __FUNCTION__);
		return ETIMEDOUT;
	}
	index++;
	
	/*word index 10*/
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_DATA_IN) =(((data[8] & new_base_msb_mask_18) >> 14)|((data[9] & lsb_mask_12)  <<  18 ));
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_MASK_IN) =(((mask[8] & new_base_msb_mask_18) >> 14)|((mask[9] & lsb_mask_12)  <<  18 ));

	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = ((BIT31) | (bank << 29) | (index << 1));

	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
	while (((temp & BIT0) != 1) && (attempts <  MAX_ATTEMPTS))
	{
		temp = 	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
		attempts++;
	}
	if(attempts == MAX_ATTEMPTS)
	{
		dagutil_warning("timeout in %s\n", __FUNCTION__);
		return ETIMEDOUT;
	}
	index++;
	
	/*word index 11*/
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_DATA_IN) =(((data[9] & new_base_msb_mask_20)>> 12) |((data[10] & lsb_mask_10 )  <<  20 ));
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_MASK_IN) =(((mask[9] & new_base_msb_mask_20)>> 12) |((mask[10] & lsb_mask_10 )  <<  20 ));

	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = ((BIT31) | (bank << 29) | (index << 1));

	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
	while (((temp & BIT0)!= 1) && (attempts <  MAX_ATTEMPTS))
	{
		temp = 	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
		attempts++;
	}
	if(attempts == MAX_ATTEMPTS)
	{
		dagutil_warning("timeout in %s\n", __FUNCTION__);
		return ETIMEDOUT;
	}
	index++;
	
	/*word index 12*/
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_DATA_IN) = (((data[10]  & new_base_msb_mask_22)  >> 10)|((mask[11] & lsb_mask_8 )  <<  22));
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_MASK_IN) = (((mask[10]  & new_base_msb_mask_22)  >> 10)|((mask[11] & lsb_mask_8 )  <<  22));

	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = ((BIT31) | (bank << 29) | (index << 1));

	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
	while (((temp & BIT0)!= 1) && (attempts <  MAX_ATTEMPTS))
	{
		temp = 	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
		attempts++;
	}
	if(attempts == MAX_ATTEMPTS)
	{
		dagutil_warning("timeout in %s\n", __FUNCTION__);
		return ETIMEDOUT;
	}
	index++;
	
	/*word index 13*/
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_DATA_IN) = (((data[11] & new_base_msb_mask_24) >> 8)|((data[12] & lsb_mask_6) <<   24));
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_MASK_IN) = (((mask[11] & new_base_msb_mask_24) >> 8)|((mask[12] & lsb_mask_6) <<   24));  

	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = ((BIT31) | (bank << 29) | (index << 1));

	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
	while (((temp & BIT0)!= 1) && (attempts <  MAX_ATTEMPTS))
	{
		temp = 	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
		attempts++;
	}
	if(attempts == MAX_ATTEMPTS)
	{
		dagutil_warning("timeout in %s\n", __FUNCTION__);
		return ETIMEDOUT;
	}
	return ESUCCESS;
}

/**
 *  * Swaps the active BANK.If BANK 0 is active activates BANK 1 and vice-versa
 *  *
 *  * @param[in]  header     The structure which contains the F/W interface
 *  * 
 *  */
void swap_active_bank(BFSStateHeaderPtr header)
{
	uint32_t temp = 0;
	temp =  *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_CONFIG_REG);
	if((temp & BIT28) == 0)/*bank 0 is active*/
	{
		
		temp = 0xc00d0020;
	}
	else
	{	
		temp = 0x400d0020;
	}
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_CONFIG_REG) = temp;
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_CONFIG_REG) = 0x00000000;
}
/**
 *  * Reads an entry from the BFS cam 
 *  * @param[in]  header    The structure which contains the F/W interface
 *  * 
 *  * @return               Returns the active BANK.
 *  */
bool get_inactive_bank(BFSStateHeaderPtr header)
{
	
	uint32_t attempts = 0;
	
	uint32_t temp =  *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_CONFIG_REG);
	
	while((((temp & BIT29) >> 29)!= 0 ) && (attempts < 50))
	{
		temp =  *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_CONFIG_REG);
		attempts ++;
	}
	if(attempts == 50)
	{
		dagutil_panic("Not able to read the bank status");
	}
	
	if((temp & BIT28) == 0)
	{
		dagutil_verbose_level(2,"Bank 0 is active \n");
		return 1;
	}
	else
	{	
		dagutil_verbose_level(2,"Bank 1 is active \n");
		return 0;
	}
}
/**
 *  * Writes an entry into the BFS cam 
 *  *
 *  * @param[in]  header     The structure which contains the F/W interface
 *  * 
 *  * @param[in]  addr       The address (index) of the TCAM entry to write.
 *  *
 *  * @param[in]  colour     The TCAM colour to be written to SRAM
 *  *                        into the data part of the entry.
 *  * @param[in]  db         The database (BANK into which the data is to be written.)

 *  * @return                Returns one of the following error co
 *  * @retval ESUCCESS       The data and mask in the tcam at the given address is as expected.
 *  */
int 
bfs_write_sram_entry(BFSStateHeaderPtr header,uint32_t db ,uint32_t address,uint32_t colour)
{
	bool bank = false;

	if( (db & 0x1) == 0)
		bank = false;
	else if ((db & 0x1) == 1)
		bank = true;
		
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_SRAM_INTERFACE)  = ((BIT31)| (bank << 29) |((address & 0x1fff) << 16) |(colour & 0xffff));

	return ESUCCESS;
}
/**
 *  * Writes an entry into the BFS SRAM 
 *  *
 *  * @param[in]  header     The structure which contains the F/W interface
 *  * 
 *  * @param[in]  addr       The address (index) of the TCAM entry to write.
 *  *
 *  * @param[in]  db         The database (BANK into which the data is to be written.)
 *  *
 *  * @param[out]  colour    The TCAM colour to be read from SRAM
 *  *
 *  * @return                Returns one of the following error co
 *  * @retval ESUCCESS       The data and mask in the tcam at the given address is as expected.
 *  */
int 
bfs_read_sram_entry(BFSStateHeaderPtr header,uint32_t db ,uint32_t address,uint32_t *colour)
{
	bool bank = false;
	uint32_t temp = 0;

	if( (db & 0x1) == 0)
		bank = false;
	else if ((db & 0x1) == 1)
		bank = true;
		
	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_SRAM_INTERFACE)  = ((BIT30)| (bank << 29) |((address & 0x1fff) << 16));
	
	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_SRAM_INTERFACE);

	*colour = temp;
	
	dagutil_verbose_level(2,"colour 0x%04x\n",*colour);

	return ESUCCESS;
}
/**
 *  * Returns the lookup width of the TCAM
 *  *
 *  * @param[in]  header     The structure which contains the F/W interface
 *  * 
 *  *
 *  * @return                Returns one of the following error codes
 *  * @retval 				 lookup_width
 *  */

int bfs_get_lookup_width(BFSStateHeaderPtr header)
{
	uint32_t lookup_width,value = 0;

	value = *(volatile unsigned int*)((uint8_t*)header->ppf_register_base + 0x4);

	lookup_width = ((value & 0xffff0000) >> 16);

	return lookup_width;
}

/**
 *  * Writes the SRAM miss value.
 *  *
 *  * @param[in]  header     The structure which contains the F/W interface
 *  * 
 *  *
 *  * @return                Returns one of the following error codes
 *  * @retval 				 void       
 *  */

void bfs_set_sram_miss_value(BFSStateHeaderPtr header,uint32_t sram_miss_value)
{
	*(volatile unsigned int*)((uint8_t*)header->ppf_register_base + 0x1C) = sram_miss_value;
	return; 
}

/**
 *  * Initialises the TCAM.
 *  *
 *  * @param[in]  header     The structure which contains the F/W interface
 *  * 
 *  *
 *  * @return                Returns one of the following error codes
 *  * @retval ESUCCESS       Initialization fo the TCAM successful.
 *  * @retval EINVAL         Argument to the function is invalid.
 *  */

int bfs_cam_initialise(BFSStateHeaderPtr header)
{
	bool inactive_bank = false;
	uint32_t data = 0;
	uint32_t attempts = 0;
	int temp = 0;
	int loop = 0;
	
	/* Sanity checking */
	if ( header == NULL )
		return EINVAL;
	
	inactive_bank = get_inactive_bank(header);
	dagutil_verbose_level(3,"write_bfscam_value  bptr %p \n",header->bfs_register_base);	
	
	if(inactive_bank)
	{
		data = ((BIT27) | (1 << 29));
	}else
	{
		data = ((BIT27) | (0 << 29));
	}

	if (header->version == 0)
	{
		for (loop = 0; loop < MAX_BFS_POSSIBLE_RULES; loop++)
		{
			*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_ADDRESS_REGISTER) = (loop & 0xffff);
			*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = data;

			attempts = 0;
			temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
	        	while (((temp & BIT0)!= 1) && (attempts <  MAX_ATTEMPTS))
    	    		{
    	        	 	temp =  *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
    	         		dagutil_microsleep(10);
    	         		attempts++;
    	    		}
    	    		if(attempts == MAX_ATTEMPTS)
    	    		{
    	          		dagutil_warning("timeout in %s\n", __FUNCTION__);
    	          		return ETIMEDOUT;
    	    		}
		}
	}
	else
	{
	
	    for (loop = 0; loop < MAX_BFS_POSSIBLE_RULES; loop++)
		{
			/*initialize programming state machine bit.*/
			attempts = 0;
			*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = (BIT1);
			
			/*write the rule number.*/	
	        	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_ADDRESS_REGISTER) = (loop & 0xffff);

	        	/*Write the bit corrosponding to the bank you want to program.*/
	        	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = (inactive_bank << 29);
	
	        	/*write the rule clear bit.*/
	        	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE) = (BIT27);

	        	/*Wait till the rule operation completed bit is set.*/	                                                                                           
	        	temp = *(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
		    	while(((temp & BIT0)!= 1) && (attempts <  MAX_ATTEMPTS))
	        	{
		         	temp = 	*(volatile unsigned int*)((uint8_t*)header->bfs_register_base + TCAM_PROGRAM_INTERFACE);
				dagutil_microsleep(1000);
		         	attempts++;
	        	}
				
	        	if(attempts == MAX_ATTEMPTS)
	        	{
		        	dagutil_warning("timeout in %s\n", __FUNCTION__);
		          	return ETIMEDOUT;
	        	}                                                                                          
       		}
	}
	return ESUCCESS;
}

