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

static dag_err_t reset_control_update_register_base(ComponentPtr component);
static int reset_control_post_initialize(ComponentPtr component);
static void reset_control_default(ComponentPtr component);
static void reset_control_dispose(ComponentPtr component);
static void reset_control_reset(ComponentPtr component);

/* HAT Register offset enum */
#define kResetControl 0x00
#define kMagicNumber  0x04
#define kWrapperReady 0x08

Attribute_t reset_control_attr[]=
{
	{
		/* Name */                 "initiate_recovery_reset",
		/* Attribute Code */       kBooleanAttributeInitiateRecoveryReset,
		/* Attribute Type */       kAttributeBoolean,
		/* Description */          "Initiates a recovery reset sequence.",
		/* Config-Status */        kDagAttrConfig,
		/* Index in register */    31,
		/* Register Address */     DAG_REG_RESET_STRATEGY,
		/* Offset */               kResetControl,
		/* Size/length */          1,
		/* Read */                 grw_iom_read,
		/* Write */                grw_iom_write,
		/* Mask */                 BIT31,
		/* 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 */                 "recovery_reset_finished",
		/* Attribute Code */       kBooleanAttributeRecoveryResetFinished,
		/* Attribute Type */       kAttributeBoolean,
		/* Description */          "If asserted indicates that recovery reset has finished.",
		/* Config-Status */        kDagAttrStatus,
		/* Index in register */    31,
		/* Register Address */     DAG_REG_RESET_STRATEGY,
		/* Offset */               kResetControl,
		/* Size/length */          1,
		/* Read */                 grw_iom_read,
		/* Write */                grw_iom_write,
		/* Mask */                 BIT23,
		/* 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(reset_control_attr) / sizeof(Attribute_t))

ComponentPtr
reset_control_get_new_component(DagCardPtr card, uint32_t index)
{
	ComponentPtr result = component_init(kComponentResetControl, card);
	reset_control_state_t* state = NULL;
	if (NULL != result)
	{
		component_set_dispose_routine(result, reset_control_dispose);
		component_set_post_initialize_routine(result, reset_control_post_initialize);
		component_set_reset_routine(result, reset_control_reset);
		component_set_default_routine(result, reset_control_default);
		component_set_update_register_base_routine(result, reset_control_update_register_base);
		component_set_name(result, "reset_control_interface");
		component_set_description(result, "The reset control register interface.");
		state = (reset_control_state_t*)malloc(sizeof(reset_control_state_t));
		state->mIndex = index;
		state->mResetControlBase = (uint32_t*)(card_get_iom_address(card) + card_get_register_address(card, DAG_REG_RESET_STRATEGY, state->mIndex));
		component_set_private_state(result, state);
	}
	return result;
}

static
dag_err_t reset_control_update_register_base(ComponentPtr component)
{
	if (1 == valid_component(component))
	{
		reset_control_state_t* state = NULL;
		DagCardPtr card;
		state = component_get_private_state(component);
		card = component_get_card(component);
		NULL_RETURN_WV(state, kDagErrGeneral);
		state->mResetControlBase = (uint32_t*)(card_get_iom_address(card) + card_get_register_address(card, DAG_REG_RESET_STRATEGY, state->mIndex)); 
		return kDagErrNone;
	}
	return kDagErrInvalidParameter;
}
static
int reset_control_post_initialize(ComponentPtr component)
{
	if (1 == valid_component(component))
	{
		DagCardPtr card = NULL;
		reset_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->mResetControlBase = (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, reset_control_attr, NB_ELEM, state->mIndex);

		return 1;
	}
	return kDagErrInvalidParameter;
}
static  
void reset_control_default(ComponentPtr component)
{
	if (1 == valid_component(component))
	{
		AttributePtr attribute = NULL;
		uint8_t val = 1;
		uint32_t ready_status = 0;
		uint32_t attempts = 0;
		DagCardPtr card = NULL;
		/* Get card reference */
		card = component_get_card(component);
		attribute = component_get_attribute(component,kBooleanAttributeInitiateRecoveryReset);
		if (attribute)
		{
			/*Ping the recovery reset bit.*/
			attribute_set_value(attribute, &val, 1);
	 	}
		attribute = component_get_attribute(component,kBooleanAttributeRecoveryResetFinished);
		if (attribute)
		{
			/*poll  the reset done bit.*/
			val = *(uint8_t*)attribute_get_value(attribute);
			while((val == 0) && (attempts < 50))
			{
				val = *(uint8_t*)attribute_get_value(attribute);
				dagutil_microsleep(200000);
				attempts++;	
			}
			if(attempts == 50)
			{
				ready_status =  *(unsigned int*) (card_get_iom_address(card) + card_get_register_address(card, DAG_REG_RESET_STRATEGY, 0) + kWrapperReady);
				dagutil_panic("Recovery Reset not finished.reset wrapper ready status %x\n",ready_status);
			}
	
	 	}
	}
}
static
void reset_control_dispose(ComponentPtr component)
{
}
static
void reset_control_reset(ComponentPtr component)
{
}




