#include "dagutil.h"
#include "dagapi.h"
#include "../include/attribute.h"
#include "../include/util/set.h"
#include "../include/card.h"
#include "../include/cards/card_initialization.h"
#include "../include/component.h"
#include "../include/util/utility.h"
#include "../include/cards/common_dagx_constants.h"
#include "../include/util/enum_string_table.h"
#include "../include/cards/dag71s_impl.h"
#include "../include/attribute_factory.h"
#include "../include/create_attribute.h"
#include "../include/components/altgx_port_component.h"
#include "../include/dag_attribute_codes.h"
#include "../include/attribute_types.h"

#define BUFFER_SIZE 1024

#define kRegStatusControl 0x00

static dag_err_t altgx_tile_update_register_base(ComponentPtr component);
static int altgx_tile_post_initialize(ComponentPtr component);
static void altgx_tile_default(ComponentPtr component);
static void altgx_tile_dispose(ComponentPtr component);
static void altgx_tile_reset(ComponentPtr component);
static dag_config_state_t altgx_port_get_state_routine(ComponentPtr component);
static void* master_slave_get_value(AttributePtr attribute);
static void master_slave_set_value(AttributePtr attribute, void* value, int length);
static void master_slave_to_string_routine(AttributePtr attribute);
static void master_slave_from_string_routine(AttributePtr attribute, const char* string);
AttributePtr altgx_get_new_line_rate_attribute(GenericReadWritePtr grw, const uint32_t *bit_masks, uint32_t len);

static void altgx_line_rate_set_value(AttributePtr attribute, void * value, int len);
static void* altgx_line_rate_get_value(AttributePtr attribute);
static void altgx_line_rate_to_string_routine(AttributePtr attribute);
static void altgx_line_rate_from_string_routine(AttributePtr attribute, const char* string);

static void altgx_wan_mode_set_value(AttributePtr attribute, void * value, int len);
static void* altgx_wan_mode_get_value(AttributePtr attribute);

static void* altgx_link_get_value(AttributePtr attribute);

static void altgx_eql_set_value(AttributePtr attribute, void * value, int len);
static void altgx_fcl_set_value(AttributePtr attribute, void * value, int len);

Attribute_t altgx_tile_attr[]=
{
    {
        /* Name */                 "eql",
        /* Attribute Code */       kBooleanAttributeEquipmentLoopback,
        /* Attribute Type */       kAttributeBoolean,
        /* Description */          "Equipment loopback",
        /* Config-Status */        kDagAttrConfig,
        /* Index in register */    9,
        /* Register Address */     DAG_REG_TILE_CTRL,
        /* Offset */               kRegStatusControl,
        /* Size/length */          1,
        /* Read */                 grw_iom_read,
        /* Write */                grw_iom_write,
        /* Mask */                 BIT3,
        /* Default Value */        0,
        /* SetValue */             altgx_eql_set_value,
        /* GetValue */             attribute_boolean_get_value,
        /* SetToString */          attribute_boolean_to_string,
        /* SetFromString */        attribute_boolean_from_string,
        /* Dispose */              attribute_dispose,
        /* PostInit */             attribute_post_initialize,
    },
    {
        /* Name */                 "fcl",
        /* Attribute Code */       kBooleanAttributeFacilityLoopback,
        /* Attribute Type */       kAttributeBoolean,
        /* Description */          "Facility loopback",
        /* Config-Status */        kDagAttrConfig,
        /* Index in register */    5,
        /* Register Address */     DAG_REG_TILE_CTRL,
        /* Offset */               kRegStatusControl,
        /* Size/length */          1,
        /* Read */                 grw_iom_read,
        /* Write */                grw_iom_write,
        /* Mask */                 BIT0,
        /* Default Value */        0,
	/* SetValue */             altgx_fcl_set_value,
        /* GetValue */             attribute_boolean_get_value,
        /* SetToString */          attribute_boolean_to_string,
        /* SetFromString */        attribute_boolean_from_string,
        /* Dispose */              attribute_dispose,
        /* PostInit */             attribute_post_initialize,
    },
    {
        /* Name */                 "master_or_slave",
        /* Attribute Code */       kUint32AttributeMasterSlave,
        /* Attribute Type */       kAttributeUint32,
        /* Description */          "Master or slave",
        /* Config-Status */        kDagAttrConfig,
        /* Index in register */    6,
        /* Register Address */     DAG_REG_TILE_CTRL,
        /* Offset */               kRegStatusControl,
        /* Size/length */          1,
        /* Read */                 grw_iom_read,
        /* Write */                grw_iom_write,
        /* Mask */                 BIT4,
        /* Default Value */        kMaster,
        /* SetValue */             master_slave_set_value,
        /* GetValue */             master_slave_get_value,
        /* SetToString */          master_slave_to_string_routine,
        /* SetFromString */        master_slave_from_string_routine,
        /* Dispose */              attribute_dispose,
        /* PostInit */             attribute_post_initialize,
    },
    {
        /* Name */                 "lock",
        /* Attribute Code */       kBooleanAttributeLock,
        /* Attribute Type */       kAttributeBoolean,
        /* Description */          "Signal lock if 1.",
        /* Config-Status */        kDagAttrStatus,
        /* Index in register */    6,
        /* Register Address */     DAG_REG_TILE_CTRL,
        /* Offset */               kRegStatusControl,
        /* Size/length */          1,
        /* Read */                 grw_iom_read,
        /* Write */                grw_iom_write,
        /* Mask */                 BIT8,
        /* Default Value */        0,
        /* SetValue */             attribute_boolean_set_value,
        /* GetValue */             attribute_boolean_get_value,
        /* SetToString */          attribute_boolean_to_string,
        /* SetFromString */        attribute_boolean_from_string,
        /* Dispose */              attribute_dispose,
        /* PostInit */             attribute_post_initialize,
    },
    {
        /* Name */                 "TXfifoerror",
        /* Attribute Code */       kBooleanAttributeFIFOError,
        /* Attribute Type */       kAttributeBoolean,
        /* Description */          "Tx FIFO error.",
        /* Config-Status */        kDagAttrStatus,
        /* Index in register */    6,
        /* Register Address */     DAG_REG_TILE_CTRL,
        /* Offset */               kRegStatusControl,
        /* Size/length */          1,
        /* Read */                 grw_iom_read,
        /* Write */                grw_iom_write,
        /* Mask */                 BIT22,
        /* Default Value */        0,
        /* SetValue */             NULL,
        /* GetValue */             attribute_boolean_get_value,
        /* SetToString */          attribute_boolean_to_string,
        /* SetFromString */        NULL,
        /* Dispose */              attribute_dispose,
        /* PostInit */             attribute_post_initialize,
    },
    {
        /* Name */                 "hi_ber.",
        /* Attribute Code */       kBooleanAttributeHiBER,
        /* Attribute Type */       kAttributeBoolean,
        /* Description */          "High BER.",
        /* Config-Status */        kDagAttrStatus,
        /* Index in register */    6,
        /* Register Address */     DAG_REG_TILE_CTRL,
        /* Offset */               kRegStatusControl,
        /* Size/length */          1,
        /* Read */                 grw_iom_read,
        /* Write */                grw_iom_write,
        /* Mask */                 BIT12,
        /* Default Value */        0,
        /* SetValue */             NULL,
        /* GetValue */             attribute_boolean_get_value,
        /* SetToString */          attribute_boolean_to_string,
        /* SetFromString */        NULL,
        /* Dispose */              attribute_dispose,
        /* PostInit */             attribute_post_initialize,
    },
    {
        /* Name */                 "tile_reset",
        /* Attribute Code */       kBooleanAttributeTileReset,
        /* Attribute Type */       kAttributeBoolean,
        /* Description */          "Resets the tile.",
        /* Config-Status */        kDagAttrConfig,
        /* Index in register */    6,
        /* Register Address */     DAG_REG_TILE_CTRL,
        /* Offset */               kRegStatusControl,
        /* Size/length */          1,
        /* Read */                 grw_iom_read,
        /* Write */                grw_iom_write,
        /* Mask */                 BIT28,
        /* Default Value */        0,
        /* SetValue */             attribute_boolean_set_value,
        /* GetValue */             attribute_boolean_get_value,
        /* SetToString */          attribute_boolean_to_string,
        /* SetFromString */        attribute_boolean_from_string,
        /* Dispose */              attribute_dispose,
        /* PostInit */             attribute_post_initialize,
    },
    {
        /* Name */                 "wan_mode",
        /* Attribute Code */       kBooleanAttributeWanMode,
        /* Attribute Type */       kAttributeBoolean,
        /* Description */          "Sets and reports if the port is in WAN mode.",
        /* Config-Status */        kDagAttrConfig,
        /* Index in register */    6,
        /* Register Address */     DAG_REG_TILE_CTRL,
        /* Offset */               kRegStatusControl,
        /* Size/length */          1,
        /* Read */                 grw_iom_read,
        /* Write */                grw_iom_write,
        /* Mask */                 BIT28,
        /* Default Value */        0,
        /* SetValue */             altgx_wan_mode_set_value,
        /* GetValue */             altgx_wan_mode_get_value,
        /* SetToString */          attribute_boolean_to_string,
        /* SetFromString */        attribute_boolean_from_string,
        /* Dispose */              attribute_dispose,
        /* PostInit */             attribute_post_initialize,
    },
    {
        /* Name */                 "link",
        /* Attribute Code */       kBooleanAttributeLink,
        /* Attribute Type */       kAttributeBoolean,
        /* Description */          "Is there a link?.",
        /* Config-Status */        kDagAttrStatus,
        /* Index in register */    6,
        /* Register Address */     DAG_REG_TILE_CTRL,
        /* Offset */               kRegStatusControl,
        /* Size/length */          1,
        /* Read */                 grw_iom_read,
        /* Write */                grw_iom_write,
        /* Mask */                 BIT13,
        /* Default Value */        0,
        /* SetValue */             NULL,
        /* GetValue */             altgx_link_get_value,
        /* SetToString */          attribute_boolean_to_string,
        /* SetFromString */        NULL,
        /* Dispose */              attribute_dispose,
        /* PostInit */             attribute_post_initialize,
    },
};

#define NB_ELEM (sizeof(altgx_tile_attr) / sizeof(Attribute_t))

ComponentPtr
altgx_tile_get_new_component(DagCardPtr card, uint32_t index)
{
	ComponentPtr result = component_init(kComponentPort, card);
	altgx_tile_state_t* state = NULL;
	if (NULL != result)
	{
		char buffer[BUFFER_SIZE];
		component_set_dispose_routine(result, altgx_tile_dispose);
		component_set_post_initialize_routine(result, altgx_tile_post_initialize);
		component_set_reset_routine(result, altgx_tile_reset);
		component_set_default_routine(result, altgx_tile_default);
		component_set_update_register_base_routine(result, altgx_tile_update_register_base);
		component_set_getstate_routine(result,altgx_port_get_state_routine);
		sprintf(buffer, "port%d", index);
		component_set_name(result, buffer);
		component_set_description(result,"altgx tile component provides user with the low level control of the tile.");
		state = (altgx_tile_state_t*)malloc(sizeof(altgx_tile_state_t));
		state->mIndex = index;
		state->mAltgxTileBase = (uint32_t*)(card_get_iom_address(card) + card_get_register_address(card, DAG_REG_TILE_CTRL, state->mIndex));
		component_set_private_state(result, state);
	}
	return result;
}


static
dag_err_t altgx_tile_update_register_base(ComponentPtr component)
{
	if (1 == valid_component(component))
	{
		altgx_tile_state_t* state = NULL;
		DagCardPtr card;
		state = component_get_private_state(component);
		card = component_get_card(component);
		NULL_RETURN_WV(state, kDagErrGeneral);
		state->mAltgxTileBase = (uint32_t*)(card_get_iom_address(card) + card_get_register_address(card, DAG_REG_TILE_CTRL, state->mIndex)); 
		return kDagErrNone;
	}
	return kDagErrInvalidParameter;
}
static
int altgx_tile_post_initialize(ComponentPtr component)
{
	if (1 == valid_component(component))
	{
		DagCardPtr card = NULL;
		AttributePtr attr = NULL;
		GenericReadWritePtr grw = NULL;
		uintptr_t address = 0;
		uint32_t attr_mask = 0;
		altgx_tile_state_t* state = NULL;
		/* Get card reference */
		card = component_get_card(component);
		/* Get counter state structure */
		state = component_get_private_state(component);
		/*the base address*/
		state->mAltgxTileBase = (uint32_t*)(card_get_iom_address(card) + card_get_register_address(card, DAG_REG_TILE_CTRL, state->mIndex));
		/* Add attribute of counter */
		read_attr_array(component, altgx_tile_attr, NB_ELEM, state->mIndex);
		attr_mask = 0xffffffff;
		grw = grw_init(card,address,grw_iom_read,grw_iom_write);	
		attr = altgx_get_new_line_rate_attribute(grw,&attr_mask,1);
		component_add_attribute(component, attr);

			
		return 1;
	}
	return kDagErrInvalidParameter;
}
static  
void altgx_tile_default(ComponentPtr component)
{
	if (1 == valid_component(component))
	{
		altgx_tile_state_t* state = NULL;
		AttributePtr attribute = NULL;
		int count;
		int index = 0;
		void *val = NULL;
		/* Get counter state structure */
		state = (altgx_tile_state_t*)component_get_private_state(component);
		count = component_get_attribute_count(component);
		for (index = 0; index < count; index++)
		{
			attribute = component_get_indexed_attribute(component, index); 
			val = attribute_get_default_value(attribute);
			attribute_set_value(attribute, &val, 1);
		}
		
	}
}
static
void altgx_tile_dispose(ComponentPtr component)
{
}
static
void altgx_tile_reset(ComponentPtr component)
{
}

static void* 
master_slave_get_value(AttributePtr attribute)
{
    uint32_t register_value;
    uint32_t value = 0;
    GenericReadWritePtr master_slave_grw = NULL;
    uint32_t *masks;

    if (1 == valid_attribute(attribute))
    {
        master_slave_grw = attribute_get_generic_read_write_object(attribute);
        assert(master_slave_grw);
        register_value = grw_read(master_slave_grw);
        masks = attribute_get_masks(attribute);
        register_value &= masks[0];

        if (register_value) 
	{
            value = kSlave;
        } else 
	{
            value = kMaster;
        }
        attribute_set_value_array(attribute, &value, sizeof(value));
        return (void *)attribute_get_value_array(attribute);
     }
    return NULL;
}

static void
master_slave_set_value(AttributePtr attribute, void* value, int length)
{
    DagCardPtr card =NULL;
    uint32_t register_value = 0;
    GenericReadWritePtr master_slave_grw = NULL;    
    master_slave_t master_slave = *(master_slave_t*)value;
    uint32_t *masks;

    card = attribute_get_card(attribute);
    if (1 == valid_attribute(attribute))
    {
        master_slave_grw = attribute_get_generic_read_write_object(attribute);
        register_value = grw_read(master_slave_grw);
        masks = attribute_get_masks(attribute);
        switch(master_slave)
        {
          case kMasterSlaveInvalid:
               /* nothing */
               break;
          case kMaster:
	       register_value &= ~masks[0]; /* set */
               break;
          case kSlave:
	       register_value |= masks[0]; /* clear */
               break;
        default:
            assert(0); /* should never get here */
        }
        grw_write(master_slave_grw, register_value);
    }
}

static void
master_slave_to_string_routine(AttributePtr attribute)
{
    master_slave_t value = *(master_slave_t*)master_slave_get_value(attribute);
    const char* temp = master_slave_to_string(value); 
    if (temp)
        attribute_set_to_string(attribute, temp);
}

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

/**
This attribute polls to see if the loaded firmware is a or a 10GE or 1G or OC192.
if it has only a XGMII then 10GE if it has only a MINIMAC it is 1GE and only sonet_pp only OC192.
If the firmware contains both an XGMII and a MINIMAC and OC192.,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
altgx_get_new_line_rate_attribute(GenericReadWritePtr grw, const uint32_t *bit_masks, uint32_t len)
{
    AttributePtr result = NULL;
    line_rate_t line_rate = kLineRateEthernet10GE;
    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_default_value(result,(void*)line_rate);
    attribute_set_valuetype(result, kAttributeUint32);
    attribute_set_getvalue_routine (result, altgx_line_rate_get_value);
    attribute_set_to_string_routine(result, altgx_line_rate_to_string_routine);
    attribute_set_setvalue_routine (result, altgx_line_rate_set_value);
    attribute_set_from_string_routine(result,altgx_line_rate_from_string_routine);
    return result;
}

/**
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.
@grw        - the generic read wirte object of the attribute.
@bit_masks  - the bit mask for the register
@len        - the length of the drb transaction.
*/
void*
altgx_line_rate_get_value(AttributePtr attribute)
{
    DagCardPtr card = NULL;
    ComponentPtr component = NULL;
    ComponentPtr root_component = NULL;
    int dagfd = 0;
    uint8_t *iom = NULL;
    line_rate_t line_rate = kLineRateInvalid;
    altgx_tile_state_t *state = 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);

    /*dual mode supported.*/
    root_component = card_get_root_component(card);
    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);
	 }
    }
    /*line_rate =  get_phy_rate_value(root_component,state->mIndex);*/
    attribute_set_value_array(attribute,&line_rate,sizeof(uint32_t));
    return (void*)attribute_get_value_array(attribute);
    
}
void
altgx_line_rate_set_value(AttributePtr attribute, void *value, int len)
{
    DagCardPtr card = NULL;
    ComponentPtr component = NULL;
    ComponentPtr root = NULL;
    ComponentPtr vcxo = NULL;
    uint8_t *iom = NULL;
    line_rate_t line_rate = kLineRateInvalid;
    altgx_tile_state_t *state = NULL;
    uint32_t attempts = 0,read_value = 0;
    float vcxo_frequency = 0;
    ComponentPtr phy_rate_component = NULL;
    AttributePtr phy_rate = NULL;
    line_rate_t set_line_rate = kLineRateInvalid;  
    
    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;
    root = component_get_parent(component);
    
    phy_rate_component = component_get_subcomponent(root,kComponentPhyMode,state->mIndex);
    if((NULL != phy_rate_component) && (line_rate != kLineRateInvalid))
    {  
	 phy_rate = component_get_attribute(phy_rate_component,kUint32AttributePhyRate);
	 if(NULL != phy_rate)
	 {
	    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
     {
	/*We assume that the phymod manager is always present on a Dag 9.2sx2 card.*/
	dagutil_warning("The user specified line rate not supported by Card/Firmware \n");
	return;
     }
     
    /*Set the VCXO*/
    vcxo = component_get_subcomponent(root,kComponentVcxo,state->mIndex);
    attribute = component_get_attribute(vcxo, kFloatAttributeVcxoFrequency);
    if (attribute)
    {
            /*ping the reset bit.*/
            if(line_rate == kLineRateEthernet10GE)
	    {
		vcxo_frequency = 644.53125;

	    }else if(line_rate == kLineRateOC192c)
	    {
		vcxo_frequency = 622.08;
            }
	    else if (line_rate == kLineRateEthernet1000)
	    {
		vcxo_frequency = 625.0;
	    }
	    else
	    {
		vcxo_frequency = 622.08;
	    }	
	    attribute_set_value(attribute, &vcxo_frequency, sizeof(float));
    }
	
    /*reset the tile*/
    /*tile_control = component_get_subcomponent(root,kComponentTileControl,state->mIndex); */ 
    attribute = component_get_attribute(component,kBooleanAttributeTileReset);
    if (attribute)
    {
	    /*ping the reset bit.*/
	    read_value = 1;
	    attribute_set_value(attribute, &read_value, sizeof(uint32_t));
    
    	    /*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 line_rate setting may not work\n");
    	   }
    }
	
}
void
altgx_line_rate_to_string_routine(AttributePtr attribute)
{
    void* temp = altgx_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
altgx_line_rate_from_string_routine(AttributePtr attribute, const char* string)
{
    if (1 == valid_attribute(attribute))
    {
        /*uint32_t phy_mode_rate = 0;*/
        line_rate_t mode = string_to_line_rate(string);
        altgx_line_rate_set_value(attribute, (void*)&mode,1);
    }
}
static dag_config_state_t
altgx_port_get_state_routine(ComponentPtr component)
{
    DagCardPtr card = NULL;
    ComponentPtr root_component = NULL;
    ComponentPtr phy_rate_component = NULL;
    AttributePtr phy_rate = NULL;
    int dagfd = 0;
    uint8_t *iom = NULL;
    altgx_tile_state_t *state = NULL;
    line_rate_t line_rate;
    
    state = component_get_private_state(component);
    card = component_get_card(component);
    dagfd = card_get_fd(card);
    iom = (uint8_t*)card_get_iom_address(card);

    root_component = card_get_root_component(card);
    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(line_rate == kLineRateEthernet10GE)
	    {
	      return kStateActive;
            }
	    else if (line_rate == kLineRateWAN)
	    {
		return kStateActive;
	    }
	    else if (line_rate == kLineRateOC192c)
	    {
		return kStateActive;
	    }
	    else
	      return kStateInactive;
	  }else
	  {
	      return kStateActive;
	  }
    }
    else
    {
        return kStateActive;
    }
}

static void altgx_wan_mode_set_value(AttributePtr attribute, void * value, int len)
{
     ComponentPtr component = NULL;
     AttributePtr line_rate_attr = NULL;
     ComponentPtr root = NULL;
     ComponentPtr xgmii = NULL;
     AttributePtr mac_wan_mode = NULL;
     altgx_tile_state_t *state = NULL;
     uint8_t reg_val = 0;
     line_rate_t line_rate = kLineRateInvalid;
     if(1 == *(uint8_t*)value)
     {
           line_rate = kLineRateWAN;
	   reg_val = 1;
     }
     else
     {
	   line_rate = kLineRateEthernet10GE;	
	   reg_val = 0;
     }
     component = attribute_get_component(attribute);
     state = component_get_private_state(component);
     line_rate_attr = component_get_attribute(component,kUint32AttributeLineRate);
     attribute_set_value(line_rate_attr,&line_rate,sizeof(line_rate_t));
     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,sizeof(uint8_t));
     }	
 }

static void* altgx_wan_mode_get_value(AttributePtr attribute)
{
  if(1 == valid_attribute(attribute))
  {
     ComponentPtr component = NULL;
     uint8_t wan_mode = 0;
     line_rate_t line_rate;
     AttributePtr line_rate_attr = NULL;
 
     component = attribute_get_component(attribute);
     line_rate_attr  = component_get_attribute(component,kUint32AttributeLineRate);
     if(NULL != line_rate_attr) 
     {
		line_rate = *(line_rate_t*)attribute_get_value(line_rate_attr);
		if(line_rate == kLineRateWAN)
		{
        		wan_mode = 1;
     		}	
     		else
     		{
        		wan_mode = 0; 
     		}
     }
     attribute_set_value_array(attribute,&wan_mode,sizeof(uint32_t));
     return (void*)attribute_get_value_array(attribute);
  }
  return NULL;
}

static void* altgx_link_get_value(AttributePtr attribute)
{
   if(1 == valid_attribute(attribute))
   {
     ComponentPtr component = NULL;
     ComponentPtr root = NULL;
     ComponentPtr phy_mode =NULL;
     AttributePtr phy_rate = NULL;
     
     uint8_t link = 0;
     uint32_t reg_val = 0;
     DagCardPtr card =NULL;
     GenericReadWritePtr grw = NULL;
     altgx_tile_state_t *state=NULL;

     component = attribute_get_component(attribute);
     card = component_get_card(component);
     root = card_get_root_component(card);
     grw = attribute_get_generic_read_write_object(attribute);
     state = component_get_private_state(component);
     phy_mode = component_get_subcomponent(root,kComponentPhyMode,state->mIndex);
     phy_rate = component_get_attribute(phy_mode,kUint32AttributePhyRate);
     if(NULL != phy_rate)
     {
               reg_val = grw_read(grw);
               reg_val &= BIT13;
	       link = (reg_val >> 13);
     }
     attribute_set_value_array(attribute,&link,sizeof(uint8_t));
     return (void*)attribute_get_value_array(attribute);
   }
   return NULL;
}

static void altgx_eql_set_value(AttributePtr attribute, void * value, int len)
{
  
    if(1 == valid_attribute(attribute))
    {
	uint8_t eql = *(uint8_t*)value;
	attribute_boolean_set_value(attribute,&eql,len);
	/** 
	Sleep for 1 milli second after setting the value.
	This is the time required for the reconfiguration of the tile to complete.
	TODO Implement a polling based method.
	*/
	

	dagutil_microsleep(10);
    }
}
static void altgx_fcl_set_value(AttributePtr attribute, void * value, int len)
{
  
    if(1 == valid_attribute(attribute))
    {
	uint8_t fcl = *(uint8_t*)value;
	attribute_boolean_set_value(attribute,&fcl,len);
	/** 
	Sleep for 1 milli second after setting the value.
	This is the time required for the reconfiguration of the tile to complete.
	TODO Implement a polling based method.
	*/
	dagutil_microsleep(1000);
    }
}
