/*
 * * Copyright (c) 2005 Endace Technology Ltd, Hamilton, New Zealand.
 * * All rights reserved.
 * *
 * * This source code is proprietary to Endace Technology Limited and no part
 * * of it may be redistributed, published or disclosed except as outlined in
 * * the written contract supplied with this product.
 * *
 * */
/*Public API headers. */
/*Internal project headers. */
#include "../include/attribute.h"
#include "../include/card.h"
#include "../include/cards/card_initialization.h"
#include "../include/component.h"
#include "../include/components/pbm_component.h"
#include "../include/util/utility.h"
#include "../include/cards/common_dagx_constants.h"
#include "../include/util/enum_string_table.h"
#include "../include/components/qa2225_framer_component.h"
#include "../include/attribute_factory.h"
#include "../include/components/sr_gpp.h"
#include "../include/create_attribute.h"

#include "dag_platform.h"
#include "dagutil.h"
#include "dagapi.h"
#define BUFFER_SIZE 1024
#define FILENAME_SIZE 256

#define STRINGIFY2( x) #x
#define STRINGIFY(x) STRINGIFY2(x)
#define PASTE2( a, b) a##b
#define PASTE( a, b) PASTE2( a, b)

#define FRAMER_BINARY framer.bin
#define PATH_SLASH /
#define QUOTE(name) #name
#define STR(macro) QUOTE(macro)

#define ROM_24K 24576

#define ROM_16K 16384
#include "../../../include/dag_component_codes.h"

typedef struct
{
	uint32_t mBase;
	int mIndex;
} port_state_t;
enum
{
	PMA_DEVICE  = 1,
	WIS_DEVICE  = 2,
	PCS_DEVICE  = 3,
	XGXS_DEVICE = 4
};

static uint8_t teng_firmware_loaded[2] = {1,1};

static char* transceiver_10GEthernet_compliance[]=
{
    "10G Base-ER, ",
    "10G Base-LRM, ",
    "10G Base-LR, ",
    "10G Base-SR, ",
	
};

static char* transceiver_1GEthernet_compliance[]=
{
    "BASE-PX, ",
    "BASE-BX10, ",
    "100BASE-FX, ",
    "100BASE-LX/LX10, ",
    "1000BASE-T, ",
    "1000BASE-CX, ",
    "1000BASE-LX, ",
    "1000BASE-SX , ",

};
/*port component. */
static void qa2225_port_dispose(ComponentPtr component);
static void qa2225_port_reset(ComponentPtr component);
static void qa2225_port_default(ComponentPtr component);
static int qa2225_port_post_initialize(ComponentPtr component);
/*static dag_config_state_t qa2225_get_state_routine(ComponentPtr component);*/
static uint32_t get_base_address(DagCardPtr card);
static uint8_t is_amcc_framer_firmware_loaded(DagCardPtr card, int port_index);

AttributePtr qa2225_wan_mode_attribute(GenericReadWritePtr grw, const uint32_t *bit_masks, uint32_t len);
void*wan_mode_get_value(AttributePtr attribute);
void wan_mode_set_value(AttributePtr attribute, void * value, int len);

AttributePtr get_new_fcl_mode_attribute(GenericReadWritePtr grw, const uint32_t *bit_masks, uint32_t len);
void fcl_set_value(AttributePtr attribute, void * value, int len);
void* fcl_get_value(AttributePtr attribute);

AttributePtr qa2225_get_new_eql_attribute(GenericReadWritePtr grw, const uint32_t *bit_masks, uint32_t len);
void eql_set_value(AttributePtr attribute, void * value, int len);
void* eql_get_value(AttributePtr attribute);

AttributePtr qa2225_get_new_masterslave_mode_attribute(GenericReadWritePtr grw, const uint32_t *bit_masks, uint32_t len);
void masterslave_mode_set_value(AttributePtr attribute, void * value, int len);
void* masterslave_mode_get_value(AttributePtr attribute);
static void qa2225_master_slave_to_string_routine(AttributePtr attribute);
static void qa2225_master_slave_from_string_routine(AttributePtr attribute, const char* string);

AttributePtr qa2225_get_new_ethernet_scrambling_attribute(GenericReadWritePtr grw, const uint32_t *bit_masks, uint32_t len);
void ethernet_scrambling_set_value(AttributePtr attribute, void * value, int len);
void* ethernet_scrambling_get_value(AttributePtr attribute);

AttributePtr qa2225_get_new_wis_scrambling_attribute(GenericReadWritePtr grw, const uint32_t *bit_masks, uint32_t len);
void wis_scrambling_set_value(AttributePtr attribute, void * value, int len);
void* wis_scrambling_get_value(AttributePtr attribute);

AttributePtr qa2225_get_new_pma_reset_attribute(GenericReadWritePtr grw, const uint32_t *bit_masks, uint32_t len);
void pma_reset_set_value(AttributePtr attribute, void * value, int len);
void* pma_reset_get_value(AttributePtr attribute);

void wis_reset_set_value(AttributePtr attribute, void * value, int len);
void* wis_reset_get_value(AttributePtr attribute);

AttributePtr qa2225_get_new_pll_lock_attribute(GenericReadWritePtr grw, const uint32_t *bit_masks, uint32_t len);
void*pll_lock_get_value(AttributePtr attribute);

AttributePtr qa2225_get_new_line_rate_attribute(GenericReadWritePtr grw, const uint32_t *bit_masks, uint32_t len);
void qa2225_line_rate_set_value(AttributePtr attribute, void * value, int len);
void* qa2225_line_rate_get_value(AttributePtr attribute);
void qa2225_line_rate_to_string_routine(AttributePtr attribute);
void qa2225_line_rate_from_string_routine(AttributePtr attribute, const char* string);

AttributePtr qa2225_loss_of_pointer_attribute(GenericReadWritePtr grw,const uint32_t *bit_masks,uint32_t len);
AttributePtr qa2225_loss_of_frame_attribute(GenericReadWritePtr grw,const uint32_t *bit_masks,uint32_t len);
AttributePtr qa2225_los_attribute(GenericReadWritePtr grw,const uint32_t *bit_masks,uint32_t len);
AttributePtr qa2225_high_ber_attribute(GenericReadWritePtr grw,const uint32_t *bit_masks,uint32_t len);
AttributePtr qa2225_get_new_tx_fault_attribute(GenericReadWritePtr grw, const uint32_t *bit_masks, uint32_t len);
AttributePtr qa2225_high_ber_latched_attribute(GenericReadWritePtr grw,const uint32_t *bit_masks,uint32_t len);
AttributePtr qa2225_get_new_link_attribute(GenericReadWritePtr grw, const uint32_t *bit_masks, uint32_t len);
AttributePtr qa2225_get_new_line_alarm_attribute(GenericReadWritePtr grw, const uint32_t *bit_masks, uint32_t len);

void enable_or_disable_rx_tx(ComponentPtr this_component, dag_attribute_code_t attr_code, uint8_t value);
void* qa2225_link_get_value(AttributePtr attribute);

#if 0
uint8_t set_phy_rate_value(ComponentPtr root,int port_number,line_rate_t line_rate);
line_rate_t get_phy_rate_value(ComponentPtr root,int port_number);
#endif

ComponentPtr
qa2225_get_new_port(DagCardPtr card, uint32_t index)
{
	ComponentPtr result = component_init(kComponentPort, card);
	if (NULL != result)
	{
		char buffer[BUFFER_SIZE];
		port_state_t* state = (port_state_t*)malloc(sizeof(port_state_t));
		component_set_dispose_routine(result, qa2225_port_dispose);
		component_set_reset_routine(result, qa2225_port_reset);
		component_set_default_routine(result, qa2225_port_default);
		component_set_post_initialize_routine(result, qa2225_port_post_initialize);
		sprintf(buffer, "port%d", index);
		component_set_name(result, buffer);
		state->mBase = get_base_address(card);
		state->mIndex = index;
		component_set_private_state(result, state);
	}
	return result;
}


static uint32_t
get_base_address(DagCardPtr card)
{
	if (1 == valid_card(card))
	{
		int i = 0;
		uint32_t register_address = 0;
		register_address = card_get_register_address(card, DAG_REG_QT2225_FRAMER, i);
		return register_address;
	}
	return 0;
}


static void
qa2225_port_dispose(ComponentPtr component)
{

}


static void
qa2225_port_reset(ComponentPtr component)
{
	dag_err_t retval = kDagErrNone;
	/* disable rx during the firmware loading time */
	enable_or_disable_rx_tx(component,kBooleanAttributeRxEnable, 0/*disable*/);
	retval = load_amcc_framer_firmware(component,NULL,kLineRateEthernet10GE);
	if ( kDagErrNone != retval )
	{
		card_set_last_error( component_get_card(component), retval);
	}
	/* enable rx back */
	enable_or_disable_rx_tx(component,kBooleanAttributeRxEnable, 1/*enable*/);
}


dag_err_t load_amcc_framer_firmware(ComponentPtr component,char *filename,line_rate_t line_rate)
{
	/* Reset */
	GenericReadWritePtr grw = NULL;
	DagCardPtr card = NULL;
	uintptr_t address = 0;
	uint32_t port_number = 0;
	uint32_t device_address = 0;
	port_state_t *state = NULL;
	uint32_t loop_index = 0;
	uint32_t value = 0;
	uint32_t register_address = 0;
	FILE *fin;
	char fname[FILENAME_SIZE];
	uint32_t count = 0;
	uint8_t *array = NULL;
	int attempts = 0;
	int heartbeat_1,heartbeat_2 = 0;

	if (0 == valid_component(component) )
	{
		return kDagErrInvalidComponent;
	}
	if(filename == NULL)
	{
		if (snprintf(fname, FILENAME_SIZE, "%s/QT2x25D_module_firmware_v2_0_3_0_MDIO.bin", STR(FRAMER_FOLDER)) >= FILENAME_SIZE )
			return kDagErrInvalidParameter;
	}
	else
	{
		if (snprintf(fname, FILENAME_SIZE, "%s", filename) >= FILENAME_SIZE)
			return kDagErrInvalidParameter;
	}
	card = component_get_card(component);
	state = component_get_private_state(component);
	if ( NULL == state )
	{
		return kDagErrInvalidComponent;
	}
	port_number = state->mIndex;

	/*Issue a soft reset.*/
	address = (0x0000 & 0xffff ) | (PMA_DEVICE << 16)| (port_number << 21);
	grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
	value = 0x8000;
	grw_write(grw,value);
	grw_dispose(grw);

	/*Hold the card in reset*/
	address = (0xc300 & 0xffff ) | (PMA_DEVICE << 16)| (port_number << 21);
	grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
	value = 0x0000;
	grw_write(grw,value);
	grw_dispose(grw);

	/*eeprom boot form 2^0 156.25MHz uC*/
	address = (0xc302 & 0xffff ) | (PMA_DEVICE << 16)| (port_number << 21);
	grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
	value = 0x0004;
	grw_write(grw,value);
	grw_dispose(grw);

	/*See if the rate supported by the Firmware is 10GE or 1GE.*/

	if (line_rate == kLineRateEthernet10GE)
	{
		/*force 10G mode.*/
		address = (0xc319 & 0xffff ) | (PMA_DEVICE << 16)| (port_number << 21);
		grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
		value = 0x0008;
		grw_write(grw,value);
		grw_dispose(grw);

	} else if (line_rate == kLineRateEthernet1000)
	{
		/*force 1GE mode.*/
		address = (0xc319 & 0xffff ) | (PMA_DEVICE << 16)| (port_number << 21);
		grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
		value = 0x0088;
		grw_write(grw,value);
		grw_dispose(grw);
	}

	/*SFP + attached.*/
	address = (0xc31a & 0xffff ) | (PMA_DEVICE << 16)| (port_number << 21);
	grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
	value = 0x0098;
	grw_write(grw,value);
	grw_dispose(grw);

	/*MAGIC  "Freeze Code Points".*/
	address = (0x0026 & 0xffff ) | (PCS_DEVICE << 16)| (port_number << 21);
	grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
	value = 0x0e00;
	grw_write(grw,value);
	grw_dispose(grw);

	/*FR4 loss parameter. Note: This register is not explained in the data sheet
	or the programmer's manual.Please refer to the Firmware release notes.
	  Also note that the following parameter has been emprically found to be working
	  even though Port A and Port B trace lengths are different. */
	address = (0x0027 & 0xffff ) | (PCS_DEVICE << 16)| (port_number << 21);
	grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
	value = 0x00a3;
	grw_write(grw,value);
	grw_dispose(grw);

	/*MAGIC  truly magic if not A528 uC wont boot..*/
	address = (0x0028 & 0xffff ) | (PCS_DEVICE << 16)| (port_number << 21);
	grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
	value = 0xa528;
	grw_write(grw,value);
	grw_dispose(grw);

	/*enable the uC.*/
	address = (0xc300 & 0xffff ) | (PMA_DEVICE << 16)| (port_number << 21);
	grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
	value = 0x0002;
	grw_write(grw,value);
	grw_dispose(grw);

	/*enable the uC.*/
	address = (0xe854 & 0xffff ) | (PCS_DEVICE << 16)| (port_number << 21);
	grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
	value = 0x00c0;
	grw_write(grw,value);
	grw_dispose(grw);

	fin = fopen(fname,"rb");
	if(NULL == fin)
	{
		fprintf( stderr, "error loading file \"%s\": %u \n", fname, errno );
		return kDagErrFirmwareLoadFailed;
	}
	/*get memory:*/
	array = malloc( sizeof(*array) * ROM_24K );
	if( NULL == array )
	{
		fprintf( stderr, "insufficient memory allocating data array: %s\n", strerror(errno) );
		return kDagErrFirmwareLoadFailed;
	}
	memset(array, 0, sizeof(*array) *ROM_24K);

	count = fread( array, sizeof(*array), ROM_24K, fin );
	if( count < ROM_24K )
	{
		if( ferror(fin) != 0 )
		{
			fprintf( stderr, "error reading file \"%s\": %u \n", fname, errno );
			free( array );
			return kDagErrFirmwareLoadFailed;
		}
		if( feof(fin) != 0 )
		{
			dagutil_verbose_level(2 , "read %lu bytes\n", (unsigned long)(count * sizeof(*array)) );
			printf("Programming the micro-controller.....for PORT %d\n",port_number);
		}
	}
	else
	{
		fprintf( stderr, "warning: file longer than %u, only first %u bytes used\n",
			ROM_24K, ROM_24K );
	}
	address = (register_address & 0xffff ) | (device_address << 16)| (port_number << 21);
	grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
	/*routine to program the amcc micro*/
	for (loop_index = 0; loop_index < ROM_24K ; loop_index++)
	{
		value = array[loop_index];
		if( loop_index < ROM_16K )
		{
			device_address = 3;
			register_address = (loop_index % ROM_16K) | 0x8000;
		}
		else
		{
			device_address = 4;
			register_address = (loop_index % ROM_16K) | 0x8000;
		}
		address = (register_address & 0xffff ) | (device_address << 16)| (port_number << 21);
		grw_set_address(grw, address);
		grw_write(grw,value);

	}
	grw_dispose(grw);

	/*enable the uC.*/
	address = (0xe854 & 0xffff ) | (PCS_DEVICE << 16)| (port_number << 21);
	grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
	value = 0x0040;
	grw_write(grw,value);
	grw_dispose(grw);

	/*check the heart beat.*/
	address = (0xd7ee & 0xffff ) | (PCS_DEVICE << 16)| (port_number << 21);
	grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
	heartbeat_1 = grw_read(grw);
	dagutil_verbose("heatbeat_1 %x\n",heartbeat_1);
	grw_dispose(grw);

	dagutil_microsleep(2000);

	address = (0xd7ee & 0xffff ) | (PCS_DEVICE << 16)| (port_number << 21);
	grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
	heartbeat_2 = grw_read(grw);
	dagutil_verbose("heatbeat_2 %x\n",heartbeat_2);
	grw_dispose(grw);

	/*poll on 0xd7fd being not 0x10(Customer Configuration attained) or 0x00(Firmware not yet running.)*/
	address = (0xd7fd & 0xffff ) | (PCS_DEVICE << 16)| (port_number << 21);
	grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
	value = grw_read(grw);
	while (((value == 0x10) || (value == 0x0)) && (attempts < 10))
	{
		dagutil_microsleep(400000);
		value = grw_read(grw);
		attempts++;
	}
	if(attempts == 10)
	{
		dagutil_warning("UC_STATUS %x \n",value);
	}else
	{
		dagutil_verbose("normal UC_STATUS %x \n",value);
	}
	grw_dispose(grw);
	if (array )
	{
		free (array);
	}
	if ( fin )
	{
		fclose (fin);
	}
	/*this delay added so that both ports can be set in slave mode.*/
	dagutil_microsleep(80000);
	return kDagErrNone;
}


uint8_t is_amcc_framer_firmware_loaded(DagCardPtr card, int port_index)
{
	GenericReadWritePtr grw = NULL;
	uintptr_t address = 0;
	int heartbeat_1 = 0 ,heartbeat_2 = 0;

	address = (0xd7ee & 0xffff ) | (PCS_DEVICE << 16)| (port_index << 21);
	grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
	/*get heart beat first time*/
	heartbeat_1 = grw_read(grw);
	dagutil_verbose("heatbeat_1 %x\n",heartbeat_1);

	dagutil_microsleep(2000);

	/*get heart beat second time*/
	heartbeat_2 = grw_read(grw);

	grw_dispose(grw);
	/* compare heart-beats. if same ,not programmed */
	if ( heartbeat_1 == heartbeat_2)
		return 0;
	else
		return 1;
}


static void
qa2225_port_default(ComponentPtr component)
{
	DagCardPtr card = NULL;
	GenericReadWritePtr grw = NULL;
	uintptr_t address = 0;
	uint32_t register_value = 0;
	uint32_t device_address = 0;
	port_state_t *state = NULL;
	AttributePtr transciever_compliance = NULL;
	ComponentPtr root = NULL;
	ComponentPtr optics = NULL;
	AttributePtr sfp_detect = NULL;
	int count = 0,loop = 0;
	const char *comp_codes = NULL;
	uint8_t optics_present = 0;
	uint8_t optics_supports_10g = 0;
	uint8_t optics_supports_1g = 0;
	AttributePtr enable_full_rate = NULL;
	uint8_t optics_full_rate = 1;
	uint8_t default_to_1g = 0;
	uint8_t reprogramming_required = 0;
	ComponentPtr phy_rate_component = NULL;
	AttributePtr phy_rate = NULL;
	line_rate_t line_rate = kLineRateEthernet10GE;
	line_rate_t set_line_rate = kLineRateInvalid;
	state = component_get_private_state(component);

	if(state->mIndex == 0x00)
		device_address = 0x0;
	else if(state->mIndex == 0x01)
		device_address = 0x1;

	card = component_get_card(component);
	root = card_get_root_component(card);
	 	
	optics = component_get_subcomponent(root,kComponentOptics,state->mIndex);
	sfp_detect = component_get_attribute(optics,kBooleanAttributeDetect);
	optics_present = *(uint8_t*)attribute_get_value(sfp_detect);
	if(optics_present)
	{
		transciever_compliance  = component_get_attribute(optics,kStringAttributeTransceiverCodes);
		comp_codes = attribute_get_to_string(transciever_compliance);
		count =  4;
		for(loop = 0; loop < count ; loop++)
		{
			if ((NULL != comp_codes) && (NULL != strstr(comp_codes,transceiver_10GEthernet_compliance[loop])))
			{
				/*10G line rate supported.*/
				optics_supports_10g = 1;
			}
		}
		count =  8;
		for(loop = 0; loop < count ; loop++)
		{
			if ((NULL != strstr(comp_codes,transceiver_1GEthernet_compliance[loop])))
			{
				/*1G line rate supported.*/
				optics_supports_1g  = 1;
			}
		}
		if((1 == optics_supports_1g) && (1 == optics_supports_10g))
		{
			enable_full_rate  = component_get_attribute(optics,kBooleanAttributeEnableFullRate);
			attribute_set_value(enable_full_rate,&optics_full_rate,sizeof(uint8_t));
		}
		if((1 == optics_supports_1g) && (0 == optics_supports_10g))
		{
			/*The optics module does not support 10G.configure the card in 1000*/
			default_to_1g = 1;
		}
	}
	phy_rate_component = component_get_subcomponent(root,kComponentPhyMode,state->mIndex);
	if(NULL != phy_rate_component)
	{
		phy_rate = component_get_attribute(phy_rate_component,kUint32AttributePhyRate);
		if(NULL != phy_rate)
		{
			line_rate = *(line_rate_t*)attribute_get_value(phy_rate);
		}
	}
	/*reload the amcc framer firmware if a) the firmware is not loaded b) the current line_rate is 1G. (we default to 10GE)*/
	if((line_rate == kLineRateEthernet1000) && (default_to_1g == 0))
	{
		line_rate = kLineRateEthernet10GE;
		reprogramming_required = 1;
	}
	else if((line_rate == kLineRateEthernet10GE) &&  (default_to_1g == 1))
	{
		teng_firmware_loaded[state->mIndex] = 0;
		line_rate = kLineRateEthernet1000;
		reprogramming_required = 1;
	}
	else if((line_rate == kLineRateEthernet1000) && (default_to_1g == 1))
	{
		teng_firmware_loaded[state->mIndex] = 0;
	}
	if((0 == is_amcc_framer_firmware_loaded(card , device_address)) || (1 == reprogramming_required))
	{
		dag_err_t retval = kDagErrNone;
		/* disable rx during the firmware loading time */
		enable_or_disable_rx_tx(component, kBooleanAttributeRxEnable, 0/*disable*/);
		retval = load_amcc_framer_firmware(component,NULL,line_rate);
		if ( kDagErrNone != retval )
		{
			card_set_last_error( card, retval);
		}
		/* enable rx back */
		enable_or_disable_rx_tx(component, kBooleanAttributeRxEnable, 1/*enble*/);
	}

	phy_rate_component = component_get_subcomponent(root,kComponentPhyMode,state->mIndex);
	if(NULL != phy_rate_component)
	{
		phy_rate = component_get_attribute(phy_rate_component,kUint32AttributePhyRate);
		if(NULL != phy_rate)
		{
			attribute_set_value(phy_rate,&line_rate,1);
			set_line_rate = *(line_rate_t*)attribute_get_value(phy_rate);
			if(set_line_rate != line_rate)
			{
				dagutil_panic("The user specified line rate is not supported by the card or F/W \n");
			}
		}
	}
	#if 0
	optics = component_get_subcomponent(root,kComponentOptics,state->mIndex);
	sfp_detect = component_get_attribute(optics,kBooleanAttributeDetect);
	optics_present = *(uint8_t*)attribute_get_value(sfp_detect);
	if(optics_present)
	{
		transciever_compliance  = component_get_attribute(optics,kStringAttributeTransceiverCodes);
		comp_codes = attribute_get_to_string(transciever_compliance);
		count =  4;
		for(loop = 0; loop < count ; loop++)
		{
			if ((NULL != comp_codes) && (NULL != strstr(comp_codes,transceiver_10GEthernet_compliance[loop])))
			{
				/*10G line rate supported.*/
				optics_supports_10g = 1;
			}
		}
		count =  8;
		for(loop = 0; loop < count ; loop++)
		{
			if ((NULL != strstr(comp_codes,transceiver_1GEthernet_compliance[loop])))
			{
				/*1G line rate supported.*/
				optics_supports_1g  = 1;
			}
		}
		if((1 == optics_supports_1g) && (1 == optics_supports_10g))
		{
			enable_full_rate  = component_get_attribute(optics,kBooleanAttributeEnableFullRate);
			attribute_set_value(enable_full_rate,&optics_full_rate,sizeof(uint8_t));
		}
	}
	#endif
	/*Places the Framer in LAN Timing Mode*/
	address = (QT_MODE_REGISTER & 0xffff ) | (PMA_DEVICE << 16)| (device_address << 21);
	grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
	register_value = grw_read(grw);
	register_value |= BIT0;
	grw_write(grw,register_value);
	grw_dispose(grw);

	/*Selects between EREFClock and SREFClock inputs for 10G reference clock*/
	address = (QT_PMA_VENDOR_SPECIFIC_REGISTER_1 & 0xffff ) | (PMA_DEVICE << 16)| (device_address << 21);
	grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
	register_value = grw_read(grw);
	register_value &= ~BIT7;
	grw_write(grw,register_value);
	grw_dispose(grw);

	/*put the framer in slave mode.*/
	address = (QT_PMA_VENDOR_SPECIFIC_REGISTER_1 & 0xffff ) | (PMA_DEVICE << 16)| (device_address << 21);
	grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
	register_value = grw_read(grw);
	register_value |= BIT9;
	grw_write(grw,register_value);
	grw_dispose(grw);
	/*Disables the PMA network loopback.*/
	address = ( QT_PMA_VENDOR_SPECIFIC_REGISTER_1 & 0xffff ) | (PMA_DEVICE << 16)| (device_address << 21);
	grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
	register_value = grw_read(grw);
	register_value &= ~BIT4;
	grw_write(grw,register_value);
	grw_dispose(grw);

	/*Disables the  XGXS system loopback.*/
	address = ( QT_XGXS_VENDOR_SPECIFIC_REGISTER_1 & 0xffff ) | (XGXS_DEVICE << 16)| (device_address << 21);
	grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
	register_value = grw_read(grw);
	register_value &= ~BIT14;
	grw_write(grw,register_value);
	grw_dispose(grw);
}


static int
qa2225_port_post_initialize(ComponentPtr component)
{
	uintptr_t address = 0;
	DagCardPtr card = NULL;
	AttributePtr attr = NULL;
	uint32_t attr_mask = 0;
	GenericReadWritePtr grw = NULL;
	uint32_t device_address = 0;
	port_state_t *state = NULL;
	/*AttributePtr  any_attr = NULL;
	uint8_t *ptr_bool = NULL;*/
	card = component_get_card(component);

	state = component_get_private_state(component);

	if(state->mIndex == 0x00)
		device_address = 0x00;
	else if(state->mIndex == 0x01)
		device_address = 0x01;

	/*Configures the chip in WAN Mode.*/
	address = 0;
	attr_mask = 0xffff;
	grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
	attr = qa2225_wan_mode_attribute(grw, &attr_mask, 1);
	component_add_attribute(component, attr);

	/*FCL*/
	address = 0;
	attr_mask = 0xffff;
	grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
	attr = get_new_fcl_mode_attribute(grw, &attr_mask, 1);
	component_add_attribute(component, attr);

	/*EQL*/
	address = 0;
	attr_mask = 0xffff;
	grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
	attr = qa2225_get_new_eql_attribute(grw, &attr_mask, 1);
	component_add_attribute(component, attr);

	/*MASTER_SLAVE*/
	address = 0;
	attr_mask = 0xffff;
	grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
	attr = qa2225_get_new_masterslave_mode_attribute(grw, &attr_mask, 1);
	component_add_attribute(component, attr);

	/*Ethernet Scrambling*/
	address = 0;
	attr_mask = 0xffff;
	grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
	attr = qa2225_get_new_ethernet_scrambling_attribute(grw, &attr_mask, 1);
	component_add_attribute(component, attr);

	/*WIS Scrambling.*/
	address = 0;
	attr_mask = 0xffff;
	grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
	attr = qa2225_get_new_wis_scrambling_attribute(grw, &attr_mask, 1);
	component_add_attribute(component, attr);

	/*PMA reset attribute..*/
	address = 0;
	attr_mask = 0xffff;
	grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
	attr = qa2225_get_new_pma_reset_attribute(grw, &attr_mask, 1);
	component_add_attribute(component, attr);

	/*PLL LOCK attribute.*/
	address = 0;
	attr_mask = 0xffff;
	grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
	attr = qa2225_get_new_pll_lock_attribute(grw, &attr_mask, 1);
	component_add_attribute(component, attr);

	/*High Bit Error Rate.*/
	address = (QT_WIS_STATUS_REGISTER_3 & 0xffff) | (PCS_DEVICE << 16) | (device_address << 21);
	attr_mask = BIT14;
	grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
	attr = qa2225_high_ber_latched_attribute(grw, &attr_mask, 1);
	component_add_attribute(component, attr);

	/*High Bit Error Rate.*/
	#if 1
	address = (QT_WIS_STATUS_REGISTER_3 & 0xffff) | (PCS_DEVICE << 16) | (device_address << 21);
	attr_mask = BIT8| BIT9 | BIT10 | BIT11 | BIT12 | BIT13;
	grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
	attr = qa2225_high_ber_attribute(grw, &attr_mask, 1);
	component_add_attribute(component, attr);
	#endif

	address = (QT_PMA_PMD_STATUS_REGISTER_2 & 0xffff) | (PMA_DEVICE << 16) | (device_address << 21);
	attr_mask = BIT11;
	grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
	attr = qa2225_get_new_tx_fault_attribute(grw,&attr_mask,1);
	component_add_attribute(component, attr);

	/*LINK*/
	address = (QT_PCS_STATUS_REGISTER_1 & 0xffff) | (PCS_DEVICE << 16) | (device_address << 21);
	attr_mask = BIT2;
	grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
	attr = qa2225_get_new_link_attribute(grw, &attr_mask, 1);
	component_add_attribute(component, attr);

	address = (QT_WIS_STATUS_REGISTER_3 & 0xffff) | (WIS_DEVICE << 16) | (device_address << 21);
	attr_mask = BIT2;
	grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
	attr = qa2225_get_new_line_alarm_attribute(grw,&attr_mask,1);
	component_add_attribute(component, attr);

	attr = qa2225_get_new_line_rate_attribute(grw,&attr_mask,1);
	component_add_attribute(component, attr);
	/*Loss of Pointer and Loss of Framer will be added in both 10G lan and 10G wan modes.*/
	#if 0
	/* check if its in WAN mode. If so add LOP and LOF attribs */
	any_attr = component_get_attribute(component, kBooleanAttributeWanMode);
	if ( ( NULL != any_attr) && (NULL != (ptr_bool = (uint8_t*)attribute_get_value(any_attr) )) && *ptr_bool )
	{
	#endif
		/*LOSS OF POINTER attribute.*/
		address = (QT_WIS_STATUS_REGISTER_3 & 0xffff) | (WIS_DEVICE << 16) | (device_address << 21);
		attr_mask = BIT0;
		grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
		attr = qa2225_loss_of_pointer_attribute(grw, &attr_mask, 1);
		component_add_attribute(component, attr);

		/*LOSS OF FRAME attribute.*/
		address = (QT_WIS_STATUS_REGISTER_3 & 0xffff) | (WIS_DEVICE << 16) | (device_address << 21);
		attr_mask = BIT7;
		grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
		attr = qa2225_loss_of_frame_attribute(grw, &attr_mask, 1);
		component_add_attribute(component, attr);
	#if 0
	}
	#endif
	return 1;
}


/**
This attribute is used the configure the card in WAN/LAN mode.If 1 - card will be configured in WAN mode.
If 0 - Card will be configured in LAN mode.
@grw - the generic read wirte object of the attribute.
@bit_masks - the bit mask for the register
@len - the length of the drb transaction.
*/
AttributePtr
qa2225_wan_mode_attribute(GenericReadWritePtr grw, const uint32_t *bit_masks, uint32_t len)
{
	AttributePtr result = NULL;
	result = attribute_init(kBooleanAttributeWanMode);
	attribute_set_generic_read_write_object(result, grw);
	attribute_set_name(result, "wan_mode");
	attribute_set_description(result, "Enables the Wan mode in QT 2225 Framer Chip");
	attribute_set_config_status(result, kDagAttrConfig);
	attribute_set_valuetype(result, kAttributeBoolean);
	attribute_set_getvalue_routine(result, wan_mode_get_value);
	attribute_set_to_string_routine(result, attribute_boolean_to_string);
	attribute_set_setvalue_routine(result, wan_mode_set_value);
	attribute_set_from_string_routine(result,attribute_boolean_from_string);
	attribute_set_masks(result,bit_masks,len);
	return result;
}


void
wan_mode_set_value(AttributePtr attribute, void *value, int len)
{
	DagCardPtr card = NULL;
	GenericReadWritePtr grw = NULL;
	ComponentPtr component = NULL;
	ComponentPtr root = NULL;
	ComponentPtr xgmii = NULL;
	ComponentPtr phy_rate_component = NULL;
	AttributePtr phy_rate = NULL;
	line_rate_t line_rate = kLineRateInvalid;
	line_rate_t set_line_rate = kLineRateInvalid;
	AttributePtr mac_wan_mode = NULL;
	uint8_t reg_val = 0;
	uintptr_t address = 0;
	uint32_t register_value = 0;
	uint32_t device_address = 0;
	port_state_t *state = NULL;
	uint32_t new_value = 0,bit_mask = 0;

	component = attribute_get_component(attribute);
	state = component_get_private_state(component);

	if(state->mIndex == 0x00)
		device_address = 0x00;
	else if(state->mIndex == 0x01)
		device_address = 0x01;

	card = attribute_get_card(attribute);
	root = card_get_root_component(card);
	/*Set the phy mod manager ,if present,to switch between 10GE/WAN mode based on whether wan_mode is ON /OFF*/
	phy_rate_component = component_get_subcomponent(root,kComponentPhyMode,state->mIndex);
	if(NULL != phy_rate_component)
	{
    	phy_rate = component_get_attribute(phy_rate_component,kUint32AttributePhyRate);
        if(NULL != phy_rate)
        {
            line_rate = *(line_rate_t*)attribute_get_value(phy_rate);
			if(line_rate == kLineRateEthernet1000)
			{
/*				dagutil_warning("lan/wan setting not supported at this line rate  \n");*/
				dagutil_warning("lan/wan setting not supported for port %d at this line rate  \n",device_address);
				return;
			}
		}
	}
	if(*(uint8_t*)value == 1)
	{
		/*Places the Framer in WAN Timing Mode*/
		address = (QT_MODE_REGISTER & 0xffff ) | (PMA_DEVICE << 16)| (device_address << 21);
		grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
		register_value = grw_read(grw);
		register_value &= ~BIT0;
		grw_write(grw,register_value);
		grw_dispose(grw);

		/*Enables WIS logic required for WAN Mode*/
		address = (QT_PMA_PMD_CONTROL_REGISTER_2 & 0xffff ) | (WIS_DEVICE << 16)| (device_address << 21);
		grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
		register_value = grw_read(grw);
		register_value |= BIT0;
		grw_write(grw,register_value);
		grw_dispose(grw);

		/*FRX_VCOSEL*/  
		address = (QT2225_FRX_VCOSEL & 0xffff ) | (PMA_DEVICE << 16)| (device_address << 21);
		grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
		register_value = grw_read(grw);
		bit_mask =  BIT1|BIT0;
		new_value = 0;
		register_value = (register_value &(~bit_mask)) | (new_value);
		grw_write(grw,register_value);
		grw_dispose(grw);

		/*FTX_VCOFREQ_SEL*/
		address = (QT2225_FTX_VCOFREQ_SEL & 0xffff ) | (PMA_DEVICE << 16)| (device_address << 21);
		grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
		register_value = grw_read(grw);
		bit_mask = BIT5|BIT6;
		new_value = 0;
		register_value = (register_value &(~bit_mask)) | (new_value << 5);
		grw_write(grw,register_value);
		grw_dispose(grw);
		
		/*The value to be set for the attribute kBooleanAttributeMacWanMode.*/
		reg_val = 1;
	}else
	{
		/*Places the Framer in LAN Timing Mode*/
		address = (QT_MODE_REGISTER & 0xffff ) | (PMA_DEVICE << 16)| (device_address << 21);
		grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
		register_value = grw_read(grw);
		register_value |= BIT0;
		grw_write(grw,register_value);
		grw_dispose(grw);

		/*Selects between EREFClock and SREFClock inputs for 10G reference clock*/
		address = (QT_PMA_VENDOR_SPECIFIC_REGISTER_1 & 0xffff ) | (PMA_DEVICE << 16)| (device_address << 21);
		grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
		register_value = grw_read(grw);
		register_value &= ~BIT7;
		grw_write(grw,register_value);
		grw_dispose(grw);
		/*FRX_VCOSEL*/  
		address = (QT2225_FRX_VCOSEL & 0xffff ) | (PMA_DEVICE << 16)| (device_address << 21);
		grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
		register_value = grw_read(grw);
		bit_mask =  BIT1|BIT0;
		new_value = 0x01;
		register_value = (register_value &(~bit_mask)) | (new_value);
		grw_write(grw,register_value);
		grw_dispose(grw);

		/*FTX_VCOFREQ_SEL*/
		address = (QT2225_FTX_VCOFREQ_SEL & 0xffff ) | (PMA_DEVICE << 16)| (device_address << 21);
		grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
		register_value = grw_read(grw);
		bit_mask = BIT5|BIT6;
		new_value = 0x01;
		register_value = (register_value &(~bit_mask)) | (new_value << 5);
		grw_write(grw,register_value);
		grw_dispose(grw);
		
		/*The value to be set for the attribute kBooleanAttributeMacWanMode.*/
		reg_val = 0;
	}
	/*No conditional removal of Loss of Pointer and Loss of Frame  attribute based on lan/wan.*/
	#if 0
	/* Depending on WAN mode on/off, add/remove LOF and LOP */
	if(*(uint8_t*)value == 1)
	{
		uint32_t attr_mask = 0;

		/* check if LOP is already there */
		any_attr = component_get_attribute(component, kBooleanAttributeLossOfPointer);
		if ( NULL == any_attr)
		{
			/* add LOP here */
			address = (QT_WIS_STATUS_REGISTER_3 & 0xffff) | (WIS_DEVICE << 16) | (device_address << 21);
			attr_mask = BIT0;
			grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
			any_attr = qa2225_loss_of_pointer_attribute(grw, &attr_mask, 1);
			component_add_attribute(component, any_attr);
		}
		any_attr = NULL;
		/* check if LOF is already there */
		any_attr = component_get_attribute(component, kBooleanAttributeLossOfFrame);
		if ( NULL == any_attr)
		{
			/* add LOF here */
			address = (QT_WIS_STATUS_REGISTER_3 & 0xffff) | (WIS_DEVICE << 16) | (device_address << 21);
			attr_mask = BIT7;
			grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
			any_attr = qa2225_loss_of_frame_attribute(grw, &attr_mask, 1);
			component_add_attribute(component, any_attr);
		}
	}
	else
	{
		/* check if LOF/LOP is there, if so remove them */
		any_attr = component_get_attribute(component, kBooleanAttributeLossOfPointer);
		if ( NULL != any_attr)
		{
			component_dispose_attribute(component, any_attr);
		}
		any_attr = NULL;
		any_attr = component_get_attribute(component, kBooleanAttributeLossOfFrame);
		if ( NULL != any_attr)
		{
			component_dispose_attribute(component, any_attr);
		}
	}
	#endif
	/*Setting the value of the attribute kBooleanAttributeMacWanMode.dagconfig tokens lan/wan expects the attributes kBooleanAttributeWanMode and kBooleanAttributeMacWan
	 Mode to be present.This code is now changed so that  it expects only kBooleanAttributeWanMode.To maintain the same functionality the set function for kBooleanAttributeWanMode has been modified 	  to internally set kBooleanAttributeMacWanMode as well,which is done below.*/
	root = component_get_parent(component);
	xgmii = component_get_subcomponent(root,kComponentXGMII,state->mIndex);
	if(NULL != xgmii)
	{
		mac_wan_mode = component_get_attribute(xgmii,kBooleanAttributeMacWanMode);
		attribute_set_value(mac_wan_mode,&reg_val,1);
	}

	/*Set the phy mod manager ,if present,to switch between 10GE/WAN mode based on whether wan_mode is ON /OFF*/
	phy_rate_component = component_get_subcomponent(root,kComponentPhyMode,state->mIndex);
	if(NULL != phy_rate_component)
    {
    	phy_rate = component_get_attribute(phy_rate_component,kUint32AttributePhyRate);
        if(NULL != phy_rate)
        {
			if(reg_val)
            {
                line_rate = kLineRateWAN;
			}	
   			else
            {
                line_rate = kLineRateEthernet10GE;
            }
            attribute_set_value(phy_rate,&line_rate,sizeof(line_rate_t));
            set_line_rate = *(line_rate_t*)attribute_get_value(phy_rate);
            if(set_line_rate != line_rate)
            {
                 dagutil_warning("The user specified line rate not supported by Card/Firmware. \n");
                 return;
            }
         }
	}
}


//TODO - checking only WIS enable may not be enough.This may require introducing no mode as well if we check all the attributes.
//If the customer uses only this interface then it should be ok.
void*
wan_mode_get_value(AttributePtr attribute)
{
	DagCardPtr card = NULL;
	GenericReadWritePtr grw = NULL;
	ComponentPtr component = NULL;
	uintptr_t address = 0;
	uint32_t register_value = 0;
	uint8_t wan_mode = 1;

	uint32_t device_address = 0;
	port_state_t *state = NULL;
	component = attribute_get_component(attribute);
	state = component_get_private_state(component);

	if(state->mIndex == 0x00)
		device_address = 0x00;
	else if(state->mIndex == 0x01)
		device_address = 0x01;

	card = attribute_get_card(attribute);

	/*Checks WIS logic required for WAN Mode*/
	address = (QT_MODE_REGISTER & 0xffff) | (WIS_DEVICE << 16)| (device_address << 21);
	grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
	register_value = grw_read(grw);
	grw_dispose(grw);
	if(((register_value & BIT0))== 0)
	{
		wan_mode = 1;
	}
	else
	{
		wan_mode = 0;
	}
	attribute_set_value_array(attribute,&wan_mode,sizeof(uint8_t));
	return (void*)attribute_get_value_array(attribute);
}


/**
This attribute is used the configure the card Facility Control Loopback(Optical Loopback ,PMA Network Loopback).If 1 - card will be configured in fcl mode. If 0 - Card will be configured in No FCL mode.
@grw - the generic read wirte object of the attribute.
@bit_masks - the bit mask for the register
@len - the length of the drb transaction.
*/
AttributePtr
get_new_fcl_mode_attribute(GenericReadWritePtr grw, const uint32_t *bit_masks, uint32_t len)
{
	AttributePtr result = NULL;
	result = attribute_init(kBooleanAttributeFacilityLoopback);
	attribute_set_generic_read_write_object(result, grw);
	attribute_set_name(result, "fcl");
	attribute_set_description(result, "Enables the fcl loopback in QT 2225 Framer Chip");
	attribute_set_config_status(result, kDagAttrConfig);
	attribute_set_valuetype(result, kAttributeBoolean);
	attribute_set_getvalue_routine(result, fcl_get_value);
	attribute_set_to_string_routine(result, attribute_boolean_to_string);
	attribute_set_setvalue_routine(result, fcl_set_value);
	attribute_set_from_string_routine(result, attribute_boolean_from_string);
	attribute_set_masks(result,bit_masks,len);
	return result;
}


void
fcl_set_value(AttributePtr attribute, void * value, int len)
{
	DagCardPtr card = NULL;
	GenericReadWritePtr grw = NULL;
	ComponentPtr component = NULL;
	AttributePtr line_rate_attr = NULL;
	uintptr_t address = 0;
	uint32_t register_value = 0;
	uint32_t line_rate_val = kLineRateInvalid;
	uint32_t device_address = 0;
	port_state_t * state = NULL;
	component = attribute_get_component(attribute);
	state = component_get_private_state(component);

	if(state->mIndex == 0x00)
		device_address = 0x00;
	else if(state->mIndex == 0x01)
		device_address = 0x01;

	card = attribute_get_card(attribute);
	line_rate_attr = component_get_attribute(component,kUint32AttributeLineRate);
	line_rate_val = *(line_rate_t*)attribute_get_value(line_rate_attr);

	if(*(uint8_t*)value == 1)
	{
		if(line_rate_val == kLineRateEthernet1000)
		{
			/*Enables the XGXS network loopback for 1G mode.*/
			address = (0xc05b & 0xffff ) | (XGXS_DEVICE << 16)| (device_address << 21);
			grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
			register_value = grw_read(grw);
			register_value = 0x2021;
			grw_write(grw,register_value);
			grw_dispose(grw);

			address = (0xc05f & 0xffff ) | (XGXS_DEVICE << 16)| (device_address << 21);
			grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
			register_value = grw_read(grw);
			register_value = 0x0100;
			grw_write(grw,register_value);
			grw_dispose(grw);

		}else
		{
			/*Enables the PMA network loopback.*/
			address = (QT_PMA_VENDOR_SPECIFIC_REGISTER_1 & 0xffff ) | (PMA_DEVICE << 16)| (device_address << 21);
			grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
			register_value = grw_read(grw);
			register_value |= BIT4| BIT9 | BIT14 | BIT10;
			grw_write(grw,register_value);
			grw_dispose(grw);
		}

	} else						 /*if 0 - No FCL*/
	{

		if(line_rate_val == kLineRateEthernet1000)
		{
			#if 0
			/*Disables the XGXS network loopback for 1G mode.*/
			address = (0xc05b & 0xffff ) | (XGXS_DEVICE << 16)| (device_address << 21);
			grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
			register_value = grw_read(grw);
			register_value = 0x2021;
			grw_write(grw,register_value);
			grw_dispose(grw);
			#endif

			address = (0xc05f & 0xffff ) | (XGXS_DEVICE << 16)| (device_address << 21);
			grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
			register_value = grw_read(grw);
			register_value = 0x0000;
			grw_write(grw,register_value);
			grw_dispose(grw);
		}else
		{
			/*Disables the PMA network loopback.*/
			address = ( QT_PMA_VENDOR_SPECIFIC_REGISTER_1 & 0xffff ) | (PMA_DEVICE << 16)| (device_address << 21);
			grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
			register_value = grw_read(grw);
			register_value &= ~BIT4;
			grw_write(grw,register_value);
			grw_dispose(grw);

			/*0 master mode - NO fcl.*/
			address = (QT_PMA_VENDOR_SPECIFIC_REGISTER_1 & 0xffff ) | (PMA_DEVICE << 16)| (device_address << 21);
			grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
			register_value = grw_read(grw);
			register_value &= ~BIT9;
			grw_write(grw,register_value);
			grw_dispose(grw);
		}
	}
}


//:TODO -only checking PMA network loopback bit.
void*
fcl_get_value(AttributePtr attribute)
{
	DagCardPtr card = NULL;
	GenericReadWritePtr grw = NULL;
	ComponentPtr component = NULL;
	AttributePtr line_rate_attr = NULL;
	line_rate_t line_rate_val = kLineRateInvalid;
	uintptr_t address = 0;
	uint32_t register_value = 0;
	uint8_t fcl = 0;
	uint32_t device_address = 0;
	port_state_t * state = NULL;
	component = attribute_get_component(attribute);
	state = component_get_private_state(component);

	if(state->mIndex == 0x00)
		device_address = 0x00;
	else if(state->mIndex == 0x01)
		device_address = 0x01;

	card = attribute_get_card(attribute);
	line_rate_attr = component_get_attribute(component,kUint32AttributeLineRate);
	line_rate_val = *(line_rate_t*)attribute_get_value(line_rate_attr);

	if(line_rate_val == kLineRateEthernet1000)
	{
		/*Check PMA Network Loopback Bit.*/
		address = (0xc05f & 0xffff ) | (XGXS_DEVICE << 16)| (device_address << 21);
		grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
		register_value = grw_read(grw);
		grw_write(grw,register_value);
		grw_dispose(grw);
		if (((register_value & BIT8)>>8) == 1)
		{
			fcl = 1;
		}
		else
		{
			fcl = 0;
		}
	}else
	{
		address = (QT_PMA_VENDOR_SPECIFIC_REGISTER_1 & 0xffff ) | (PMA_DEVICE << 16)| (device_address << 21);
		grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
		register_value = grw_read(grw);
		grw_write(grw,register_value);
		grw_dispose(grw);
		if(((register_value & BIT4)>>4) == 1)
		{
			fcl = 1;
		}
		else
		{
			fcl = 0;
		}
	}
	attribute_set_value_array(attribute,&fcl,sizeof(fcl));
	return (void*)attribute_get_value_array(attribute);
}


/**
This attribute is used the configure the card Equipment Control Loopback(Logic / System Loopback , XGXS Loopback).
If 1 - card will be configured in eql mode.
If 0 - Card will be configured in no eql mode.
@grw - the generic read wirte object of the attribute.
@bit_masks - the bit mask for the register
@len - the length of the drb transaction.
*/
AttributePtr
qa2225_get_new_eql_attribute(GenericReadWritePtr grw, const uint32_t *bit_masks, uint32_t len)
{
	AttributePtr result = NULL;
	result = attribute_init(kBooleanAttributeEquipmentLoopback);
	attribute_set_generic_read_write_object(result, grw);
	attribute_set_name(result, "eql");
	attribute_set_description(result, "Enables the eql loopback in QT 2225 Framer Chip");
	attribute_set_config_status(result, kDagAttrConfig);
	attribute_set_valuetype(result, kAttributeBoolean);
	attribute_set_getvalue_routine(result, eql_get_value);
	attribute_set_to_string_routine(result, attribute_boolean_to_string);
	attribute_set_setvalue_routine(result, eql_set_value);
	attribute_set_from_string_routine(result, attribute_boolean_from_string);
	attribute_set_masks(result,bit_masks,len);
	return result;
}


void
eql_set_value(AttributePtr attribute, void * value, int len)
{
	DagCardPtr card = NULL;
	GenericReadWritePtr grw = NULL;
	ComponentPtr component = NULL;
	AttributePtr line_rate_attr = NULL;
	uintptr_t address = 0;
	uint32_t register_value = 0;
	uint32_t line_rate_val = kLineRateInvalid;
    uint32_t device_address = 0;
	port_state_t * state = NULL;
	component = attribute_get_component(attribute);
	state = component_get_private_state(component);

	if(state->mIndex == 0x00)
		device_address = 0x00;
	else if(state->mIndex == 0x01)
		device_address = 0x01;

	card = attribute_get_card(attribute);
	line_rate_attr = component_get_attribute(component,kUint32AttributeLineRate);
    line_rate_val = *(line_rate_t*)attribute_get_value(line_rate_attr);

	if(*(uint8_t*)value == 1)
	{   
		if(line_rate_val == kLineRateEthernet1000)
		{
			/*Enables the PMA loopback data override.*/
            address = (0xc001 & 0xffff ) | (PMA_DEVICE << 16)| (device_address << 21);
            grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
            register_value = grw_read(grw);
            register_value |= BIT15;
            grw_write(grw,register_value);
            grw_dispose(grw);

			/*Enables the PMA SYSTEM loopback.*/
            address = (0xf053 & 0xffff ) | (PMA_DEVICE << 16)| (device_address << 21);
            grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
            register_value = grw_read(grw);
            register_value |= BIT6;
            grw_write(grw,register_value);
            grw_dispose(grw);

		}else
		{
			/*Enables the XGXS SYSTEM loopback.*/
			address = (QT_XGXS_VENDOR_SPECIFIC_REGISTER_1 & 0xffff ) | (XGXS_DEVICE << 16)| (device_address << 21);
			grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
			register_value = grw_read(grw);
			register_value |= (BIT14| BIT15);
			grw_write(grw,register_value);
			grw_dispose(grw);
		}
	}else/*if 0 - No EQL*/
	{
		if(line_rate_val == kLineRateEthernet1000)
        {
			/*Disables the  PMA system loopback.*/
			address = ( 0xf053 & 0xffff ) | (PMA_DEVICE << 16)| (device_address << 21);
			grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
			register_value = grw_read(grw);
			register_value &= ~BIT6;
			grw_write(grw,register_value);
			grw_dispose(grw);

			/*Disables the  PMA loopback data override.*/
			address = ( 0Xc001 & 0xffff ) | (PMA_DEVICE << 16)| (device_address << 21);
			grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
			register_value = grw_read(grw);
			register_value &= ~BIT15;
			grw_write(grw,register_value);
			grw_dispose(grw);

		}else
		{
			/*Disables the  XGXS system loopback.*/
			address = ( QT_XGXS_VENDOR_SPECIFIC_REGISTER_1 & 0xffff ) | (XGXS_DEVICE << 16)| (device_address << 21);
			grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
			register_value = grw_read(grw);
			register_value &= ~BIT14;
			grw_write(grw,register_value);
			grw_dispose(grw);
		}
	}
}


void*
eql_get_value(AttributePtr attribute)
{
	DagCardPtr card = NULL;
	GenericReadWritePtr grw = NULL;
	ComponentPtr component = NULL;
	AttributePtr line_rate_attr = NULL;
    line_rate_t line_rate_val = kLineRateInvalid;
	uintptr_t address = 0;
	uint32_t register_value = 0;
	uint8_t eql = 0;
	uint32_t device_address = 0;
	port_state_t *state = NULL;
	component = attribute_get_component(attribute);
	state = component_get_private_state(component);

	if(state->mIndex == 0x00)
		device_address = 0x00;
	else if(state->mIndex == 0x01)
		device_address = 0x01;

	card = attribute_get_card(attribute);
	line_rate_attr = component_get_attribute(component,kUint32AttributeLineRate);
    line_rate_val = *(line_rate_t*)attribute_get_value(line_rate_attr);

	if(line_rate_val == kLineRateEthernet1000)
    {
		address = (0xf053 & 0xffff ) | (PMA_DEVICE << 16)| (device_address << 21);
        grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
        register_value = grw_read(grw);
        grw_write(grw,register_value);
        grw_dispose(grw);
        if (((register_value & BIT6) >>6) == 1)
        {
            eql = 1;
        }
        else
        {
            eql = 0;
        }
	}else
	{
		address = ( QT_XGXS_VENDOR_SPECIFIC_REGISTER_1 & 0xffff ) | (XGXS_DEVICE << 16)| (device_address << 21);
		grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
		register_value = grw_read(grw);
		grw_write(grw,register_value);
		grw_dispose(grw);
		if(((register_value & BIT14)>>14) == 1)
		{
			eql = 1;
		}
		else
		{
			eql = 0;
		}
	}
    attribute_set_value_array(attribute,&eql,sizeof(eql));
    return (void*)attribute_get_value_array(attribute);
}


/**
This attribute is used the configure the card in Master/Slave mode.
@grw - the generic read wirte object of the attribute.
@bit_masks - the bit mask for the register
@len - the length of the drb transaction.
*/
//:TODO - need to see if we need master slave mode as uint32 or a boolean
AttributePtr
qa2225_get_new_masterslave_mode_attribute(GenericReadWritePtr grw, const uint32_t *bit_masks, uint32_t len)
{
	AttributePtr result = NULL;
	result = attribute_init(kUint32AttributeMasterSlave);
	attribute_set_generic_read_write_object(result, grw);
	attribute_set_name(result, "master_or_slave");
	attribute_set_description(result, "Configures the QT 2225 Framer Chip in master mode.");
	attribute_set_config_status(result, kDagAttrConfig);
	attribute_set_valuetype(result, kAttributeUint32);
	attribute_set_getvalue_routine(result, masterslave_mode_get_value);
	attribute_set_to_string_routine(result, qa2225_master_slave_to_string_routine);
	attribute_set_setvalue_routine(result, masterslave_mode_set_value);
	attribute_set_from_string_routine(result, qa2225_master_slave_from_string_routine);
	attribute_set_masks(result,bit_masks,len);
	return result;
}


void
masterslave_mode_set_value(AttributePtr attribute, void * value, int len)
{
	DagCardPtr card = NULL;
	GenericReadWritePtr grw = NULL;
	ComponentPtr component = NULL;
	uintptr_t address = 0;
	uint32_t register_value = 0;
	master_slave_t master_slave = *(master_slave_t*)value;
	uint32_t device_address = 0;
	port_state_t * state = NULL;
	component = attribute_get_component(attribute);
	state = component_get_private_state(component);

	if(state->mIndex == 0x00)
		device_address = 0x00;
	else if(state->mIndex == 0x01)
		device_address = 0x01;

	card = attribute_get_card(attribute);

	if(kMaster == master_slave)	 /*put the framer in master mode.*/
	{
		/*Forces the crystal reference clock should be used.*/
		address = (QT_PMA_VENDOR_SPECIFIC_REGISTER_1 & 0xffff) | (PMA_DEVICE << 16)| (device_address << 21);
		grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
		register_value = grw_read(grw);
		register_value &= ~BIT9;
		grw_write(grw,register_value);
		grw_dispose(grw);

		/*FXT_LTIME_EN*/
		address = (QT_PMA_VENDOR_SPECIFIC_REGISTER_1 & 0xffff) | (PMA_DEVICE << 16)| (device_address << 21);
		grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
		register_value = grw_read(grw);
		register_value &= ~BIT14;
		grw_write(grw,register_value);
		grw_dispose(grw);

								 /* put the framer in Slave mode*/
	}else if (kSlave == master_slave)
	{
		address = (QT_PMA_VENDOR_SPECIFIC_REGISTER_1 & 0xffff ) | (PMA_DEVICE << 16)| (device_address << 21);
		grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
		register_value = grw_read(grw);
		register_value |= BIT9;
		grw_write(grw,register_value);
		grw_dispose(grw);
	}
}


void*
masterslave_mode_get_value(AttributePtr attribute)
{
	DagCardPtr card = NULL;
	GenericReadWritePtr grw = NULL;
	ComponentPtr component = NULL;
	uintptr_t address = 0;
	uint32_t register_value = 0;
	master_slave_t master_slave  = kMasterSlaveInvalid;
	uint32_t device_address = 0;
	port_state_t * state = NULL;
	component = attribute_get_component(attribute);
	state = component_get_private_state(component);

	if(state->mIndex == 0x00)
		device_address = 0x00;
	else if(state->mIndex == 0x01)
		device_address = 0x01;

	card = attribute_get_card(attribute);

	address = (QT_PMA_VENDOR_SPECIFIC_REGISTER_1 & 0xffff ) | (PMA_DEVICE << 16)| (device_address << 21);
	grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
	register_value = grw_read(grw);
	grw_write(grw,register_value);
	grw_dispose(grw);
	if((register_value & BIT9) == 0)
	{
		address = (QT_PMA_VENDOR_SPECIFIC_REGISTER_1 & 0xffff ) | (PMA_DEVICE << 16)| (device_address << 21);
		grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
		register_value = grw_read(grw);
		grw_write(grw,register_value);
		grw_dispose(grw);
		if(((register_value & BIT14) >>14) == 0)
		{
			/*master*/
			master_slave = kMaster;
			attribute_set_value_array(attribute,&master_slave,sizeof(master_slave));
			return (void*)attribute_get_value_array(attribute);
		}else
		{
			/*slave*/
			master_slave = kSlave;
			attribute_set_value_array(attribute,&master_slave,sizeof(master_slave));
			return (void*)attribute_get_value_array(attribute);
		}
	}
	else
	{
		/*slave*/
		master_slave = kSlave;
		attribute_set_value_array(attribute,&master_slave,sizeof(master_slave));
		return (void*)attribute_get_value_array(attribute);
	}
}


void
qa2225_master_slave_to_string_routine(AttributePtr attribute)
{
	master_slave_t value = *(master_slave_t*)masterslave_mode_get_value(attribute);
	const char* temp = master_slave_to_string(value);
	if (temp)
		attribute_set_to_string(attribute, temp);
}


static void
qa2225_master_slave_from_string_routine(AttributePtr attribute, const char* string)
{
	master_slave_t value = string_to_master_slave(string);
	if (kMasterSlaveInvalid != value)
		masterslave_mode_set_value(attribute, (void*)&value, sizeof(master_slave_t));
}


/**
This attribute is used to enable/disable 10G Ethernet Scrambling.
If 1 - 10G Ethernet Scrambling will be enabled.
If 0 - 10G Ethernet Scrambling will be disabled.
@grw - the generic read wirte object of the attribute.
@bit_masks - the bit mask for the register
@len - the length of the drb transaction.
*/
AttributePtr
qa2225_get_new_ethernet_scrambling_attribute(GenericReadWritePtr grw, const uint32_t *bit_masks, uint32_t len)
{
	AttributePtr result = NULL;
	result = attribute_init(kBooleanAttribute10GEthernetScrambling);
	attribute_set_generic_read_write_object(result, grw);
	attribute_set_name(result, "ethernet_scrambling");
	attribute_set_description(result, "Ethernet scrambling enable/disable");
	attribute_set_config_status(result, kDagAttrConfig);
	attribute_set_valuetype(result, kAttributeBoolean);
	attribute_set_getvalue_routine(result, ethernet_scrambling_get_value);
	attribute_set_to_string_routine(result, attribute_boolean_to_string);
	attribute_set_setvalue_routine(result, ethernet_scrambling_set_value);
	attribute_set_from_string_routine(result,attribute_boolean_from_string);
	attribute_set_masks(result,bit_masks,len);
	return result;
}


void
ethernet_scrambling_set_value(AttributePtr attribute, void * value, int len)
{
	DagCardPtr card = NULL;
	GenericReadWritePtr grw = NULL;
	ComponentPtr component = NULL;
	uintptr_t address = 0;
	uint32_t register_value = 0;
	uint32_t device_address = 0;
	port_state_t * state = NULL;
	component = attribute_get_component(attribute);
	state = component_get_private_state(component);

	if(state->mIndex == 0x00)
		device_address = 0x00;
	else if(state->mIndex == 0x01)
		device_address = 0x01;

	card = attribute_get_card(attribute);

	if(*(uint8_t*)value == 1)	 /*10G Ethernet Scrambling/Descrambling enable.*/
	{
		address = (QT_XGXS_VENDOR_SPECIFIC_REGISTER_1 & 0xffff ) | (PCS_DEVICE << 16)| (device_address << 21);
		grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
		register_value = grw_read(grw);
		register_value &= ~BIT2;
		grw_write(grw,register_value);
		grw_dispose(grw);

		address = (QT_XGXS_VENDOR_SPECIFIC_REGISTER_1 & 0xffff ) | (PCS_DEVICE << 16)| (device_address << 21);
		grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
		register_value = grw_read(grw);
		register_value &= ~BIT1;
		grw_write(grw,register_value);
		grw_dispose(grw);

	}else/*10G Ethernet Scrambling/Descrambling disable/bypass.*/
	{
		address = (QT_XGXS_VENDOR_SPECIFIC_REGISTER_1 & 0xffff ) | (PCS_DEVICE << 16)| (device_address << 21);
		grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
		register_value = grw_read(grw);
		register_value |= BIT2;
		grw_write(grw,register_value);
		grw_dispose(grw);

		address = (QT_XGXS_VENDOR_SPECIFIC_REGISTER_1 & 0xffff ) | (PCS_DEVICE << 16)| (device_address << 21);
		grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
		register_value = grw_read(grw);
		register_value |= BIT1;
		grw_write(grw,register_value);
		grw_dispose(grw);
	}
}


void*
ethernet_scrambling_get_value(AttributePtr attribute)
{
	DagCardPtr card = NULL;
	GenericReadWritePtr grw = NULL;
	ComponentPtr component = NULL;
	uintptr_t address = 0;
	uint8_t ethernet_scrambling = 0;
	uint32_t register_value = 0;
	uint32_t device_address = 0;
	port_state_t * state = NULL;

	component = attribute_get_component(attribute);
	state = component_get_private_state(component);

	if(state->mIndex == 0x00)
		device_address = 0x00;
	else if(state->mIndex == 0x01)
		device_address = 0x01;

	card = attribute_get_card(attribute);

	address = (QT_XGXS_VENDOR_SPECIFIC_REGISTER_1 & 0xffff ) | (PCS_DEVICE << 16)| (device_address << 21);
	grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
	register_value = grw_read(grw);
	grw_dispose(grw);
	if(((((register_value & BIT2) >> 2)== 0) && ((register_value & BIT1) >> 1) == 0))
	{
		ethernet_scrambling = 1;
		attribute_set_value_array(attribute,&ethernet_scrambling,sizeof(ethernet_scrambling));
		return (void*)attribute_get_value_array(attribute);
	}else
	{
		ethernet_scrambling = 0;
		attribute_set_value_array(attribute,&ethernet_scrambling,sizeof(ethernet_scrambling));
		return (void*)attribute_get_value_array(attribute);
	}
}


AttributePtr
qa2225_get_new_wis_scrambling_attribute(GenericReadWritePtr grw, const uint32_t *bit_masks, uint32_t len)
{
	AttributePtr result = NULL;
	result = attribute_init(kBooleanAttributeWISScrambling);
	attribute_set_generic_read_write_object(result, grw);
	attribute_set_name(result, "wis_scrambling");
	attribute_set_description(result, "WIS scrambling enable/disable");
	attribute_set_config_status(result, kDagAttrConfig);
	attribute_set_valuetype(result, kAttributeBoolean);
	attribute_set_getvalue_routine(result, wis_scrambling_get_value);
	attribute_set_to_string_routine(result, attribute_boolean_to_string);
	attribute_set_setvalue_routine(result, wis_scrambling_set_value);
	attribute_set_from_string_routine(result,attribute_boolean_from_string);
	attribute_set_masks(result,bit_masks,len);
	return result;
}


void
wis_scrambling_set_value(AttributePtr attribute, void * value, int len)
{
	DagCardPtr card = NULL;
	GenericReadWritePtr grw = NULL;
	ComponentPtr component = NULL;
	uintptr_t address = 0;
	uint32_t register_value = 0;
	uint32_t device_address = 0;
	port_state_t * state = NULL;
	component = attribute_get_component(attribute);
	state = component_get_private_state(component);

	if(state->mIndex == 0x00)
		device_address = 0x00;
	else if(state->mIndex == 0x01)
		device_address = 0x01;

	card = attribute_get_card(attribute);

	if(*(uint8_t*)value == 1)	 /*WIS Scrambling enable.*/
	{
		address = (QT_PMA_VENDOR_SPECIFIC_REGISTER_1 & 0xffff ) | (WIS_DEVICE << 16)| (device_address << 21);
		grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
		register_value = grw_read(grw);
		register_value &= ~BIT0;
		grw_write(grw,register_value);
		grw_dispose(grw);

		address = (QT_PMA_VENDOR_SPECIFIC_REGISTER_1 & 0xffff ) | (WIS_DEVICE << 16)| (device_address << 21);
		grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
		register_value = grw_read(grw);
		register_value &= ~BIT1;
		grw_write(grw,register_value);
		grw_dispose(grw);

	}else						 /*WIS Scrambling enable.*/
	{

		address = (QT_PMA_VENDOR_SPECIFIC_REGISTER_1 & 0xffff ) | (WIS_DEVICE << 16)| (device_address << 21);
		grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
		register_value = grw_read(grw);
		register_value |= BIT0;
		grw_write(grw,register_value);
		grw_dispose(grw);

		address = (QT_PMA_VENDOR_SPECIFIC_REGISTER_1 & 0xffff ) | (WIS_DEVICE << 16)| (device_address << 21);
		grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
		register_value = grw_read(grw);
		register_value |= BIT1;
		grw_write(grw,register_value);
		grw_dispose(grw);
	}
}


void*
wis_scrambling_get_value(AttributePtr attribute)
{
	DagCardPtr card = NULL;
	GenericReadWritePtr grw = NULL;
	ComponentPtr component = NULL;
	uintptr_t address = 0;
	uint8_t wis_scrambling = 0;
	uint32_t register_value = 0;
	uint32_t device_address = 0;
	port_state_t * state = NULL;
	component = attribute_get_component(attribute);
	state = component_get_private_state(component);

	if(state->mIndex == 0x00)
		device_address = 0x00;
	else if(state->mIndex == 0x01)
		device_address = 0x01;

	card = attribute_get_card(attribute);

	address = (QT_PMA_VENDOR_SPECIFIC_REGISTER_1 & 0xffff ) | (WIS_DEVICE << 16)| (device_address << 21);
	grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
	register_value = grw_read(grw);
	grw_dispose(grw);
	if((register_value & 0x3) == 0)
	{
		wis_scrambling = 1;
		attribute_set_value_array(attribute,&wis_scrambling,sizeof(wis_scrambling));
		return (void*)attribute_get_value_array(attribute);
	}else
	{
		wis_scrambling = 0;
		attribute_set_value_array(attribute,&wis_scrambling,sizeof(wis_scrambling));
		return (void*)attribute_get_value_array(attribute);
	}
}


/**
This attribute is used to issue a PMA reset.Also works a global reset for the PHY.
If 1 - will issue a PMA reset.Please not that this reset is self clearing.
If 0 - Normal Operation.
@grw - the generic read wirte object of the attribute.
@bit_masks - the bit mask for the register
@len - the length of the drb transaction.
*/
AttributePtr
qa2225_get_new_pma_reset_attribute(GenericReadWritePtr grw, const uint32_t *bit_masks, uint32_t len)
{
	AttributePtr result = NULL;
	result = attribute_init(kBooleanAttributeGTPPMAReset);
	attribute_set_generic_read_write_object(result, grw);
	attribute_set_name(result, "pma_reset");
	attribute_set_description(result, "PMA reset.Works as a global reset for the PHY.");
	attribute_set_config_status(result, kDagAttrConfig);
	attribute_set_valuetype(result, kAttributeBoolean);
	attribute_set_getvalue_routine(result, pma_reset_get_value);
	attribute_set_to_string_routine(result, attribute_boolean_to_string);
	attribute_set_setvalue_routine(result, pma_reset_set_value);
	attribute_set_from_string_routine(result, attribute_boolean_from_string);
	attribute_set_masks(result,bit_masks,len);
	return result;
}


void
pma_reset_set_value(AttributePtr attribute, void * value, int len)
{
	DagCardPtr card = NULL;
	GenericReadWritePtr grw = NULL;
	ComponentPtr component = NULL;
	uintptr_t address = 0;
	uint32_t register_value = 0;

	uint32_t device_address = 0;
	port_state_t * state = NULL;
	component = attribute_get_component(attribute);
	state = component_get_private_state(component);

	if(state->mIndex == 0x00)
		device_address = 0x00;
	else if(state->mIndex == 0x01)
		device_address = 0x01;

	card = attribute_get_card(attribute);

	if(*(uint8_t*)value == 1)	 /*If '1' issue a PMA reset.*/
	{
		address = (QT_PMA_PMD_CONTROL_REGISTER_1 & 0xffff ) | (PMA_DEVICE << 16)| (device_address << 21);
		grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
		register_value = grw_read(grw);
		register_value |= BIT15;
		grw_write(grw,register_value);
		grw_dispose(grw);
	}
	else
	{
		address = (QT_PMA_PMD_CONTROL_REGISTER_1 & 0xffff ) | (PMA_DEVICE << 16)| (device_address << 21);
		grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
		register_value = grw_read(grw);
		register_value &= ~BIT15;
		grw_write(grw,register_value);
		grw_dispose(grw);
	}
}


void*
pma_reset_get_value(AttributePtr attribute)
{
	DagCardPtr card = NULL;
	GenericReadWritePtr grw = NULL;
	ComponentPtr component = NULL;
	uintptr_t address = 0;
	uint8_t pma_reset = 0;
	uint32_t register_value = 0;
	uint32_t device_address = 0;
	port_state_t * state = NULL;
	component = attribute_get_component(attribute);
	state = component_get_private_state(component);

	if(state->mIndex == 0x00)
		device_address = 0x00;
	else if(state->mIndex == 0x01)
		device_address = 0x01;

	card = attribute_get_card(attribute);

	address = (QT_PMA_PMD_CONTROL_REGISTER_1 & 0xffff ) | (PMA_DEVICE << 16)| (device_address << 21);
	grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
	register_value = grw_read(grw);
	grw_dispose(grw);
								 /*should never return '1'. is a self clearing bit.*/
	if((((register_value && BIT15) >> 15)== 0))
	{
		pma_reset = 0;
		attribute_set_value_array(attribute,&pma_reset,sizeof(pma_reset));
		return (void*)attribute_get_value_array(attribute);
	}else
	{
		pma_reset = 1;
		attribute_set_value_array(attribute,&pma_reset,sizeof(pma_reset));
		return (void*)attribute_get_value_array(attribute);
	}
}


/**
This attribute is indicates if the core has a lock on the incoming datastream
If 1 - the core has a lock on the incoming data stream.
If 0 - the core has not locked on the incoming data stream.The Rx XAUI interface will receive idle sequences.
@grw - the generic read wirte object of the attribute.
@bit_masks - the bit mask for the register
@len - the length of the drb transaction.
*/
AttributePtr
qa2225_get_new_pll_lock_attribute(GenericReadWritePtr grw, const uint32_t *bit_masks, uint32_t len)
{
	AttributePtr result = NULL;
	result = attribute_init(kBooleanAttributeLock);
	attribute_set_generic_read_write_object(result, grw);
	attribute_set_name(result, "lock");
	attribute_set_description(result, "PLL has Lock on incoming data stream.");
	attribute_set_config_status(result, kDagAttrStatus);
	attribute_set_valuetype(result, kAttributeBoolean);
	attribute_set_getvalue_routine(result, pll_lock_get_value);
	attribute_set_to_string_routine(result, attribute_boolean_to_string);
	attribute_set_masks(result,bit_masks,len);
	return result;
}


void*
pll_lock_get_value(AttributePtr attribute)
{
	DagCardPtr card = NULL;
	GenericReadWritePtr grw = NULL;
	ComponentPtr component = NULL;
	uintptr_t address = 0;
	uint8_t pll_lock = 0;
	uint32_t register_value = 0;
	uint32_t device_address = 0;
	port_state_t * state = NULL;
	component = attribute_get_component(attribute);
	state = component_get_private_state(component);

	if(state->mIndex == 0x00)
		device_address = 0x00;
	else if(state->mIndex == 0x01)
		device_address = 0x01;

	card = attribute_get_card(attribute);

	address = (QT_PMA_PMD_STATUS_REGISTER_1 & 0xffff ) | (PMA_DEVICE << 16)| (device_address << 21);
	grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
	register_value = grw_read(grw);
	grw_dispose(grw);
	if((((register_value & BIT2) >> 2)== 0))
	{
		pll_lock = 0;
		attribute_set_value_array(attribute,&pll_lock,sizeof(pll_lock));
		return (void*)attribute_get_value_array(attribute);
	}else
	{
		pll_lock = 1;
		attribute_set_value_array(attribute,&pll_lock,sizeof(pll_lock));
		return (void*)attribute_get_value_array(attribute);
	}
}


/**
This status attribute latches high on the detection of a loss of pointer.
If 1 - loss of pointer detected.
If 0 - No loss of pointer detected.
@grw - the generic read wirte object of the attribute.
@bit_masks - the bit mask for the register
@len - the length of the drb transaction.
*/
AttributePtr
qa2225_loss_of_pointer_attribute(GenericReadWritePtr grw,const uint32_t *bit_masks,uint32_t len)
{
	AttributePtr result = NULL;
	result = attribute_init(kBooleanAttributeLossOfPointer);
	attribute_set_generic_read_write_object(result, grw);
	attribute_set_name(result, "loss_of_pointer");
	attribute_set_description(result, "Loss of  Pointer detected.");
	attribute_set_config_status(result, kDagAttrStatus);
	attribute_set_valuetype(result, kAttributeBoolean);
	attribute_set_getvalue_routine(result, attribute_boolean_get_value);
	attribute_set_to_string_routine(result, attribute_boolean_to_string);
	attribute_set_masks(result,bit_masks,len);
	return result;
}


/**
This status attribute latches high when the WIS has a loss of Frame.
If 1 - loss of frame detected.
If 0 - No loss of frame detected.
@grw - the generic read wirte object of the attribute.
@bit_masks - the bit mask for the register
@len - the length of the drb transaction.
*/
AttributePtr
qa2225_loss_of_frame_attribute(GenericReadWritePtr grw,const uint32_t *bit_masks,uint32_t len)
{
	AttributePtr result = NULL;
	result = attribute_init(kBooleanAttributeLossOfFrame);
	attribute_set_generic_read_write_object(result, grw);
	attribute_set_name(result, "loss_of_frame");
	attribute_set_description(result, "Loss of  Frame.");
	attribute_set_config_status(result, kDagAttrStatus);
	attribute_set_valuetype(result, kAttributeBoolean);
	attribute_set_getvalue_routine(result, attribute_boolean_get_value);
	attribute_set_to_string_routine(result, attribute_boolean_to_string);
	attribute_set_masks(result,bit_masks,len);
	return result;
}


//:TODO may not need this attribute.
/**
This status attribute latches high when the PMA detectes a LOS.no light!!
If 1 - loss of signal detected.
If 0 - No loss of signal detected.
@grw - the generic read wirte object of the attribute.
@bit_masks - the bit mask for the register
@len - the length of the drb transaction.
*/
AttributePtr
qa2225_los_attribute(GenericReadWritePtr grw,const uint32_t *bit_masks,uint32_t len)
{
	AttributePtr result = NULL;
	result = attribute_init(kBooleanAttributeLossOfSignal);
	attribute_set_generic_read_write_object(result, grw);
	attribute_set_name(result, "los");
	attribute_set_description(result, "Receiver Loss Of Signal Status.");
	attribute_set_config_status(result, kDagAttrStatus);
	attribute_set_valuetype(result, kAttributeBoolean);
	attribute_set_getvalue_routine(result, attribute_boolean_get_value);
	attribute_set_to_string_routine(result, attribute_boolean_to_string);
	attribute_set_masks(result,bit_masks,len);
	return result;
}


/**
This status attribute is a 6-bit non rollover clear on read,counter that counts every sync header error detected by the frame synchroniszer.
@grw - the generic read wirte object of the attribute.
@bit_masks - the bit mask for the register
@len - the length of the drb transaction.
*/
AttributePtr
qa2225_high_ber_attribute(GenericReadWritePtr grw,const uint32_t *bit_masks,uint32_t len)
{
	AttributePtr result = NULL;
	result = attribute_init(kUint32AttributeBERCounter);
	attribute_set_generic_read_write_object(result, grw);
	attribute_set_name(result, "ber_counter");
	attribute_set_description(result, "Bit error rate counter.");
	attribute_set_config_status(result, kDagAttrStatus);
	attribute_set_valuetype(result, kAttributeUint32);
	attribute_set_getvalue_routine(result, attribute_uint32_get_value);
	attribute_set_to_string_routine(result, attribute_uint32_to_string);
	attribute_set_masks(result,bit_masks,len);
	return result;
}


/**
This status attribute is a 6-bit non rollover clear on read,counter that counts every sync header error detected by the frame synchroniszer.
@grw - the generic read wirte object of the attribute.
@bit_masks - the bit mask for the register
@len - the length of the drb transaction.
*/
AttributePtr
qa2225_high_ber_latched_attribute(GenericReadWritePtr grw,const uint32_t *bit_masks,uint32_t len)
{
	AttributePtr result = NULL;
	result = attribute_init(kBooleanAttributeHiBER);
	attribute_set_generic_read_write_object(result, grw);
	attribute_set_name(result, "high_ber");
	attribute_set_description(result, "High_BER.");
	attribute_set_config_status(result, kDagAttrStatus);
	attribute_set_valuetype(result, kAttributeBoolean);
	attribute_set_getvalue_routine(result, attribute_boolean_get_value);
	attribute_set_to_string_routine(result, attribute_boolean_to_string);
	attribute_set_masks(result,bit_masks,len);
	return result;
}


/**
This attribute is latched high if there is a TX_FAULT or the FTX_PLL is not locked.
If 1 - there is transmit local fault
If 0 - there is no transmit local fault
@grw - the generic read wirte object of the attribute.
@bit_masks - the bit mask for the register
@len - the length of the drb transaction.
*/
AttributePtr
qa2225_get_new_tx_fault_attribute(GenericReadWritePtr grw, const uint32_t *bit_masks, uint32_t len)
{
	AttributePtr result = NULL;
	result = attribute_init(kBooleanAttributeTxFault);
	attribute_set_generic_read_write_object(result, grw);
	attribute_set_name(result, "tx_fault");
	attribute_set_description(result, "Indicates a fault condition in the Tx Path.");
	attribute_set_config_status(result, kDagAttrStatus);
	attribute_set_valuetype(result, kAttributeBoolean);
	attribute_set_getvalue_routine(result, attribute_boolean_get_value);
	attribute_set_to_string_routine(result, attribute_boolean_to_string);
	attribute_set_masks(result,bit_masks,len);
	return result;
}


/**
This attribute is latched high PMA locked to the Rx signal
PMA locked to the receive signal == (frxlock = receivepath PLL is in lock )AND (internal_los = no signal loss
If 1 - there is link
If 0 - there is no link
@grw - the generic read wirte object of the attribute.
@bit_masks - the bit mask for the register
@len - the length of the drb transaction.
*/
AttributePtr
qa2225_get_new_link_attribute(GenericReadWritePtr grw, const uint32_t *bit_masks, uint32_t len)
{
	AttributePtr result = NULL;
	result = attribute_init(kBooleanAttributeLink);
	attribute_set_generic_read_write_object(result, grw);
	attribute_set_name(result, "link");
	attribute_set_description(result, "Indicates whether the link is up.");
	attribute_set_config_status(result, kDagAttrStatus);
	attribute_set_valuetype(result, kAttributeBoolean);
	attribute_set_getvalue_routine(result, qa2225_link_get_value);
	attribute_set_to_string_routine(result, attribute_boolean_to_string);
	attribute_set_masks(result,bit_masks,len);
	return result;
}


/**
This attribute is latched high on detection of WIS line fault.
latched high on a WIS line fault.
If 1 - WIS detected a line fault
If 0 - No line fault in WIS
@grw - the generic read wirte object of the attribute.
@bit_masks - the bit mask for the register
@len - the length of the drb transaction.
*/
AttributePtr
qa2225_get_new_line_alarm_attribute(GenericReadWritePtr grw, const uint32_t *bit_masks, uint32_t len)
{
	AttributePtr result = NULL;
	result = attribute_init(kBooleanAttributeLineAlarmIndicationSignal);
	attribute_set_generic_read_write_object(result, grw);
	attribute_set_name(result, "alarm_indication_signal");
	attribute_set_description(result, "Indicates a WIS line fault.");
	attribute_set_config_status(result, kDagAttrStatus);
	attribute_set_valuetype(result, kAttributeBoolean);
	attribute_set_getvalue_routine(result, attribute_boolean_get_value);
	attribute_set_to_string_routine(result, attribute_boolean_to_string);
	attribute_set_masks(result,bit_masks,len);
	return result;
}


void enable_or_disable_rx_tx(ComponentPtr this_component, dag_attribute_code_t attr_code, uint8_t value)
{
	AttributePtr enable_attribute = NULL;
	ComponentPtr root_component = NULL;
	ComponentPtr any_component = NULL;
	port_state_t *state = NULL;
	dag_err_t prv_cs_error;

	/* FIXME just to restore the prvious error. If compt/attrib exist, set the value.Don't set error if not found?? */
	prv_cs_error = card_get_last_error( component_get_card(this_component));
	state = component_get_private_state(this_component);
	root_component = card_get_root_component(component_get_card(this_component));
	any_component = component_get_subcomponent(root_component, kComponentXGMII, (int) state->mIndex);
	if ( NULL == any_component)
	{
		/* restore  prvious error */
		card_set_last_error( component_get_card(this_component), prv_cs_error);
		return ;
	}
	enable_attribute = component_get_attribute(any_component, attr_code);
	if ( NULL == enable_attribute )
	{
		/* restore  prvious error */
		card_set_last_error( component_get_card(this_component), prv_cs_error);
		return ;
	}
	attribute_set_value(enable_attribute, &value, sizeof(uint8_t));
	return ;
}


/**
This attribute polls to see if the loaded firmware is a 1GE or a 10GE
if it has only a XGMII then 10GE if it has only a MINIMAC it is 1GE.
If the firmware contains both an XGMII and a MINIMAC,The phy_rate
is determined from the rate register.
If 1 - It is in 1GE mode
If 0 - It is in 10GE mode.
@grw        - the generic read wirte object of the attribute.
@bit_masks  - the bit mask for the register
@len        - the length of the drb transaction.
*/
AttributePtr
qa2225_get_new_line_rate_attribute(GenericReadWritePtr grw, const uint32_t *bit_masks, uint32_t len)
{
	AttributePtr result = NULL;
	result = attribute_init(kUint32AttributeLineRate);
	attribute_set_name(result, "line_rate");
	attribute_set_description(result, "Sets the line rate to a specific speed.");
	attribute_set_config_status(result, kDagAttrConfig);
	attribute_set_valuetype(result, kAttributeUint32);
	attribute_set_getvalue_routine (result, qa2225_line_rate_get_value);
	attribute_set_to_string_routine(result, qa2225_line_rate_to_string_routine);
	attribute_set_setvalue_routine (result, qa2225_line_rate_set_value);
	attribute_set_from_string_routine(result,qa2225_line_rate_from_string_routine);
	return result;
}


void
qa2225_line_rate_set_value(AttributePtr attribute, void *value, int len)
{
	DagCardPtr card = NULL;
	ComponentPtr component = NULL;
	ComponentPtr root = NULL;
	ComponentPtr tile_control = NULL;
	ComponentPtr optics = NULL;
	AttributePtr transciever_compliance = NULL;
	AttributePtr sfp_detect = NULL;
	uint8_t *iom = NULL;
	uint8_t minimac_present = 0;
	uint8_t xgmii_present = 0;
	uint8_t optics_supports_rate = 0;
	int count = 0,loop = 0,retval = 0;
	const char *comp_codes = NULL;
	dag_reg_t regs[DAG_REG_MAX_ENTRIES];
	line_rate_t line_rate = kLineRateInvalid;
	port_state_t *state = NULL;
	uint8_t optics_present = 0;
	uint32_t attempts = 0,read_value = 0;
	AttributePtr enable_full_rate = NULL;
	uint8_t optics_full_rate = 0;
	ComponentPtr phy_rate_component = NULL;
	AttributePtr phy_rate = NULL;
	line_rate_t set_line_rate = kLineRateInvalid;
	line_rate_t read_phy_rate = kLineRateInvalid;
	AttributePtr wan_mode_attr = NULL;
	uint8_t wan_mode_val = 0;
	component = attribute_get_component(attribute);
	state = component_get_private_state(component);
	card = component_get_card(component);
	iom = (uint8_t*)card_get_iom_address(card);
	line_rate = *(uint32_t*)value;
	count = dag_reg_find((char*)iom, DAG_REG_MINIMAC , regs);
	if ( count > 0 )
	{
		minimac_present = 1;
	}
	count = dag_reg_find((char*) iom, DAG_REG_XGMII , regs);
	if (count > 0)
	{
		xgmii_present = 1;
	}
	if ((1 == minimac_present) && (1 != xgmii_present))
	{

	} else if ((1 != minimac_present) && (1 == xgmii_present))
	{
		if ((line_rate == kLineRateEthernet10GE))
		{
			/*Turn off wan mode attribute.*/
			wan_mode_val = 0;
		}
		else if((line_rate == kLineRateWAN))
		{
			/*Turn on wan mode attribute*/
			wan_mode_val = 1;
		}else
		{
			dagutil_warning("line rate not supported on this card \n");
			return;
		}
		wan_mode_attr =  component_get_attribute(component,kBooleanAttributeWanMode);
		attribute_set_value(wan_mode_attr,&wan_mode_val,sizeof(uint8_t));
	} else if ((1 == minimac_present) && (1 == xgmii_present))
	{
		if ((line_rate != kLineRateEthernet1000) && (line_rate != kLineRateEthernet10GE) && (line_rate != kLineRateWAN))
		{
			dagutil_warning("line rate not supported on this card \n");
			return;
		}
		root = component_get_parent(component);
		optics = component_get_subcomponent(root,kComponentOptics,state->mIndex);
		sfp_detect = component_get_attribute(optics,kBooleanAttributeDetect);
		optics_present = *(uint8_t*)attribute_get_value(sfp_detect);
		if (optics_present)
		{
			transciever_compliance  = component_get_attribute(optics,kStringAttributeTransceiverCodes);
			comp_codes = attribute_get_to_string(transciever_compliance);
		}
		/*Get the optics - see if it is dual rate.*/
		if (line_rate == kLineRateEthernet1000)
		{
			if (optics_present)
			{
				count =  8;
				for (loop = 0; loop < count ; loop++)
				{
					if ((NULL != strstr(comp_codes,transceiver_1GEthernet_compliance[loop])))
					{
						/*1G line rate supported.*/
						optics_supports_rate  = 1;
					}
				}
			}
		}
		else if ((line_rate == kLineRateEthernet10GE)|| (line_rate == kLineRateWAN))
		{
			if (optics_present)
			{
				count =  4;
				for (loop = 0; loop < count ; loop++)
				{
					if ((NULL != comp_codes) && (NULL != strstr(comp_codes,transceiver_10GEthernet_compliance[loop])))
					{
						/*10G line rate supported.*/
						optics_supports_rate = 1;
					}
				}
			}
		}
		/*Set the phymod manager.*/
		if (optics_supports_rate || !(optics_present))
		{
			phy_rate_component = component_get_subcomponent(root,kComponentPhyMode,state->mIndex);
			if(NULL != phy_rate_component)
			{
				phy_rate = component_get_attribute(phy_rate_component,kUint32AttributePhyRate);
				if(NULL != phy_rate)
				{
					read_phy_rate = *(line_rate_t*)attribute_get_value(phy_rate);
					if((line_rate == kLineRateEthernet10GE))
					{
						line_rate = kLineRateEthernet10GE;
						wan_mode_val = 0;
					}else if((line_rate == kLineRateWAN))
					{
						line_rate = kLineRateWAN;
						wan_mode_val = 1;
					}
					attribute_set_value(phy_rate,&line_rate,sizeof(line_rate_t));
					set_line_rate = *(line_rate_t*)attribute_get_value(phy_rate);
					if(set_line_rate != line_rate)
					{
						dagutil_warning("The user specified line rate not supported by Card/Firmware. \n");
						return;
					}
				}
			}
			else
			{
				/*Dag 9.2x2 has a 10G only image(which supports both lan and wan.).This image will not have a phymod manager.*/
				/*dagutil_warning("The user specified line rate not supported by Card/Firmware \n");*/
			}

			/*Switch to the user specified mode.*/

			/*switch the rate of the optics module*/
			enable_full_rate  = component_get_attribute(optics,kBooleanAttributeEnableFullRate);

			if ((kLineRateEthernet10GE == *(uint32_t*)value) || (kLineRateWAN == *(uint32_t*)value))
			{
				optics_full_rate = 1;
			}
			else if (kLineRateEthernet1000 == *(uint32_t*)value)
			{
				optics_full_rate = 0;
			}
			attribute_set_value(enable_full_rate,&optics_full_rate,sizeof(uint8_t));
			/*We reload the framer firmware in the following cases.
 			 * current_phy_rate = 1G and user_specified_line_rate = 10G/WAN 			
 			 * current_phy_rate = 10G/wan and user_specified_line_rate = 1G.
 			 * if micro is not programmed.
 			 * */
			if(((read_phy_rate == kLineRateEthernet1000) && ((line_rate == kLineRateEthernet10GE) || (line_rate == kLineRateWAN))) ||
			   (((read_phy_rate == kLineRateWAN) || (read_phy_rate == kLineRateEthernet10GE)) && (line_rate == kLineRateEthernet1000))||
			   (0 == is_amcc_framer_firmware_loaded(card , state->mIndex)))
			{
				
				enable_or_disable_rx_tx(component, kBooleanAttributeRxEnable, 0/*disable*/);
				line_rate = *(uint32_t*)value;
				retval = load_amcc_framer_firmware(component,NULL,line_rate);
				if ( kDagErrNone != retval )
				{
					card_set_last_error( card, retval);
				}
				/* enable rx back */
				enable_or_disable_rx_tx(component, kBooleanAttributeRxEnable, 1/*enble*/);
			
				/*switch the transciever to the specified mode and reset the tile*/
				tile_control = component_get_subcomponent(root,kComponentTileControl,state->mIndex);
				attribute = component_get_attribute(tile_control,kBooleanAttributeTileReset);
				if (attribute)
				{
					/*ping the reset bit.*/
					read_value = 1;
					attribute_set_value(attribute, &read_value, 1);
				}
				/*poll  the reset done bit.*/
				read_value = *(uint8_t*)attribute_get_value(attribute);
				while((read_value != 0) && (attempts < 50))
				{
					read_value = *(uint8_t*)attribute_get_value(attribute);
					dagutil_microsleep(200000);
					attempts++;
				}
				if(attempts == 50)
				{
					dagutil_warning("tile reset was unsuccessful.The user specified line rate change may not work. \n");
				}
			}
		}
		/*We will modify the wan mode attribute only if the line rate is not 1000*/
		if(line_rate != kLineRateEthernet1000)
		{	
			wan_mode_attr =  component_get_attribute(component,kBooleanAttributeWanMode);
			attribute_set_value(wan_mode_attr,&wan_mode_val,1);
		}
	}else
	{
		/*This condition shlould never happen.*/
		dagutil_panic("Unsupported firmware configuration.Please contact support@endace.com \n");
	}
}


/**
This function checks to see if the loaded firmware is a 1GE or a 10GE
if it has only a XGMII then 10GE if it has only a MINIMAC it is 1GE.
If the firmware contains both an XGMII and a MINIMAC,then the rate
has to be determined from the rate register.
@attribute  - the line rate attribue object
*/
void*
qa2225_line_rate_get_value(AttributePtr attribute)
{
	DagCardPtr card = NULL;
	ComponentPtr component = NULL;
	ComponentPtr root_component = NULL;
	int dagfd = 0;
	uint8_t *iom = NULL;
	uint8_t minimac_present = 0;
	uint8_t xgmii_present = 0;
	int count = 0;
	dag_reg_t regs[DAG_REG_MAX_ENTRIES];
	line_rate_t line_rate = kLineRateInvalid;
	port_state_t *state = NULL;
	AttributePtr wan_mode = NULL;
	uint8_t* wan_mode_val = NULL;
	ComponentPtr phy_rate_component = NULL;
	AttributePtr phy_rate = NULL;
	component = attribute_get_component(attribute);
	state = component_get_private_state(component);
	card = component_get_card(component);
	dagfd = card_get_fd(card);
	iom = (uint8_t*)card_get_iom_address(card);

	count = dag_reg_find((char*)iom, DAG_REG_MINIMAC , regs);
	if ( count > 0 )
	{
		minimac_present = 1;
	}
	count = dag_reg_find((char*) iom, DAG_REG_XGMII , regs);
	if (count > 0)
	{
		xgmii_present = 1;
	}
	if ((1 == minimac_present) && (1 != xgmii_present))
	{
		line_rate =  kLineRateEthernet1000;
		attribute_set_value_array(attribute,&line_rate,sizeof(uint32_t));
		return (void*)attribute_get_value_array(attribute);

	} else if ((1 != minimac_present) && (1 == xgmii_present))
	{
		wan_mode = component_get_attribute(component,kBooleanAttributeWanMode);
		if((NULL != wan_mode) && (NULL != (wan_mode_val = (uint8_t*)attribute_get_value(wan_mode))) && *wan_mode_val)
			line_rate = kLineRateWAN;
		else
			line_rate = kLineRateEthernet10GE;

		attribute_set_value_array(attribute,&line_rate,sizeof(uint32_t));
		return (void*)attribute_get_value_array(attribute);

	} else if ((1 == minimac_present) && (1 == xgmii_present))
	{
		/*dual mode supported.*/
		root_component = card_get_root_component(card);
		wan_mode = component_get_attribute(component,kBooleanAttributeWanMode);
		phy_rate_component = component_get_subcomponent(root_component,kComponentPhyMode,state->mIndex);
		if(NULL != phy_rate_component)
		{
			phy_rate = component_get_attribute(phy_rate_component,kUint32AttributePhyRate);
			if(NULL != phy_rate)
			{
				line_rate = *(line_rate_t*)attribute_get_value(phy_rate);
				if((kLineRateEthernet10GE  == line_rate))
				{
					if((NULL != wan_mode) && (NULL != (wan_mode_val = (uint8_t*)attribute_get_value(wan_mode))) && *wan_mode_val)
						line_rate = kLineRateWAN;
				}
			}
		}
		attribute_set_value_array(attribute,&line_rate,sizeof(uint32_t));
		return (void*)attribute_get_value_array(attribute);
	} else
	{
		/*This condition shlould never happen.*/
		return NULL;
	}
}


void
qa2225_line_rate_to_string_routine(AttributePtr attribute)
{
	void* temp = qa2225_line_rate_get_value(attribute);
	const char* string = NULL;
	line_rate_t lr;
	if (temp)
	{
		lr = *(line_rate_t*)temp;
		string = line_rate_to_string(lr);
		if (string)
			attribute_set_to_string(attribute, string);
	}
}


void
qa2225_line_rate_from_string_routine(AttributePtr attribute, const char* string)
{
	if (1 == valid_attribute(attribute))
	{
		line_rate_t mode = string_to_line_rate(string);
		qa2225_line_rate_set_value(attribute, (void*)&mode,1);
	}
}


void* qa2225_link_get_value(AttributePtr attribute)
{
	DagCardPtr card = NULL;
        GenericReadWritePtr grw = NULL;
        ComponentPtr component = NULL;
	ComponentPtr root = NULL;
	ComponentPtr minimac = NULL;
        uintptr_t address = 0;
        uint8_t link = 0;
        uint32_t register_value = 0;
        uint32_t device_address = 0;
	AttributePtr line_rate_attr = NULL;
	AttributePtr minimac_link = NULL;
        line_rate_t line_rate_val = kLineRateInvalid;
        port_state_t * state = NULL;
        component = attribute_get_component(attribute);
        state = component_get_private_state(component);

        if(state->mIndex == 0x00)
                device_address = 0x00;
        else if(state->mIndex == 0x01)
                device_address = 0x01;

        card = attribute_get_card(attribute);
        line_rate_attr = component_get_attribute(component,kUint32AttributeLineRate);
        line_rate_val = *(line_rate_t*)attribute_get_value(line_rate_attr);
	
	if(line_rate_val == kLineRateEthernet1000)
	{
		root = component_get_parent(component);
		minimac = component_get_subcomponent(root,kComponentMiniMac,state->mIndex);
		minimac_link = component_get_attribute(minimac,kBooleanAttributeMacLink);
		link = *(uint8_t*)attribute_get_value(minimac_link);
	}else
	{
		address = (QT_PCS_STATUS_REGISTER_1 & 0xffff) | (PCS_DEVICE << 16) | (device_address << 21);
	        grw = grw_init(card, address, grw_generic_mdio_read, grw_generic_mdio_write);
	        register_value = grw_read(grw);
	        grw_dispose(grw);
	        if((((register_value & BIT2) >> 2)== 0))
	        {
        	        link = 0;
	        }else
	        {
        	        link = 1;
	        }
	}
	attribute_set_value_array(attribute,&link,sizeof(uint8_t));
	return (void*)attribute_get_value_array(attribute);
}

uint8_t 
ten_gigabits_firmware_loaded(int index)
{
	return teng_firmware_loaded[index]; 
}
