#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/tile_control_component.h"
#include "../include/dag_attribute_codes.h"
#include "../include/attribute_types.h"

static dag_err_t tile_control_update_register_base(ComponentPtr component);
static int tile_control_post_initialize(ComponentPtr component);
static void tile_control_default(ComponentPtr component);
static void tile_control_dispose(ComponentPtr component);
static void tile_control_reset(ComponentPtr component);

/*DRB offsets for Tile Control Module.*/
#define kTileControl  0x00
#define kTileStatus1  0x04
#define kTileStatus2  0x08


Attribute_t tile_control_attr[]=
{
	{
		/* Name */                 "tile_reset",
		/* Attribute Code */       kBooleanAttributeTileReset,
		/* Attribute Type */       kAttributeBoolean,
		/* Description */          "Resets the tile.",
		/* Config-Status */        kDagAttrConfig,
		/* Index in register */    31,
		/* Register Address */     DAG_REG_TILE_CTRL,
		/* Offset */               kTileControl,
		/* 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,
	},
};

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

ComponentPtr
tile_control_get_new_component(DagCardPtr card, uint32_t index)
{
	ComponentPtr result = component_init(kComponentTileControl, card);
	tile_control_state_t* state = NULL;
	if (NULL != result)
	{
		component_set_dispose_routine(result, tile_control_dispose);
		component_set_post_initialize_routine(result, tile_control_post_initialize);
		component_set_reset_routine(result, tile_control_reset);
		component_set_default_routine(result, tile_control_default);
		component_set_update_register_base_routine(result, tile_control_update_register_base);
		component_set_name(result, "tile_control_interface");
		state = (tile_control_state_t*)malloc(sizeof(tile_control_state_t));
		state->mIndex = index;
		state->mTileControlBase = (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 tile_control_update_register_base(ComponentPtr component)
{
	if (1 == valid_component(component))
	{
		tile_control_state_t* state = NULL;
		DagCardPtr card;
		state = component_get_private_state(component);
		card = component_get_card(component);
		NULL_RETURN_WV(state, kDagErrGeneral);
		state->mTileControlBase = (uint32_t*)(card_get_iom_address(card) + card_get_register_address(card, DAG_REG_TILE_CTRL, state->mIndex)); 
		return kDagErrNone;
	}
	return kDagErrInvalidParameter;
}
static
int tile_control_post_initialize(ComponentPtr component)
{
	if (1 == valid_component(component))
	{
		DagCardPtr card = NULL;
		tile_control_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->mTileControlBase = (uint32_t*)(card_get_iom_address(card) + card_get_register_address(card, DAG_REG_RESET_STRATEGY, state->mIndex));
		/* Add attribute of counter */
		read_attr_array(component, tile_control_attr, NB_ELEM, state->mIndex);

		return 1;
	}
	return kDagErrInvalidParameter;
}
static  
void tile_control_default(ComponentPtr component)
{
	if (1 == valid_component(component))
	{
		AttributePtr attribute = NULL;
		uint8_t val = 1;
		uint32_t attempts = 0;
		DagCardPtr card = NULL;
		/* Get card reference */
		card = component_get_card(component);
		attribute = component_get_attribute(component,kBooleanAttributeTileReset);
		if (attribute)
		{
			/*Ping the recovery reset bit.*/
			attribute_set_value(attribute, &val, 1);
	 	}
		/*poll  the reset done bit.*/
		val = *(uint8_t*)attribute_get_value(attribute);
		if((val != 0) && (attempts < 50))
		{
			val = *(uint8_t*)attribute_get_value(attribute);
			dagutil_microsleep(200000);
			attempts++;	
		}
		if(attempts == 50)
		{
			dagutil_panic("Tile Reset not successful\n");
		}
	}
}
static
void tile_control_dispose(ComponentPtr component)
{
}
static
void tile_control_reset(ComponentPtr component)
{
}

