/**
* @file icss_statistics.h
*
* @brief Storm prevention implementation
* @details		Contains functions for implementing a storm prevention scheme for
* 				the ICSS based ethernet switch. This is done through a credit based
* 				scheme where only a particular number of packets are allowed in a
* 				given amount of time, this is specified through a credit which expires
* 				at the end of a time period.
*
* \par
* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
* \par
*/
/* ========================================================================== */
/*                             Include Files                                  */
/* ========================================================================== */
#include "evmAM335x.h"
#include "icss_stormControl.h"

/* ========================================================================== */
/*                            Global Variables                                */
/* ========================================================================== */

/**Storm prevention control information*/
stormPrevention controlBMcast[2];

/* ========================================================================== */
/*                          Function Definitions                              */
/* ========================================================================== */
/**
* @brief Initialize the storm prevention table for both ports
*
* @retval none
*/
void initStormPreventionTable() {

	setCreditValue(DEFAULT_CREDITS, HWPORT0);
	setCreditValue(DEFAULT_CREDITS, HWPORT1);

	enableStormPrevention(HWPORT0);
	enableStormPrevention(HWPORT1);
}
/**
* @brief   Set the credit value for broadcast packets used in storm prevention
*
* @param creditValue number of packets allowed in a given time
* @param portnum port number on which value is to be set
*
* @retval none
*/
void setCreditValue(Uint16 creditValue, Uint8 portnum) {

	if (portnum > HWPORT1) {
		return;
	}

	controlBMcast[portnum].credits = creditValue;
}

/**
* @brief   Disable storm prevention algorithm for broadcast packets on a particular port
*
* @param portnum port number on which storm prevention is to be enabled
*
* @retval none
*/
void disableStormPrevention(Uint8 portnum) {
	Uint8 *controlPointer;

	if (portnum > HWPORT1) {
		return;
	}
	controlBMcast[portnum].suppressionEnabled = 0;

	if(portnum == HWPORT0) {
		controlPointer = (Uint8*)(PRU0_DRAM_BASE_ADDRESS + STORM_PREVENTION_OFFSET);
	} else {
		controlPointer = (Uint8*)(PRU1_DRAM_BASE_ADDRESS + STORM_PREVENTION_OFFSET);
	}
	*(controlPointer) = controlBMcast[portnum].suppressionEnabled;
}
/**
* @brief   Enable storm prevention algorithm on a particular port
*
* @param portnum port number on which storm prevention is to be enabled
*
* @retval none
*/
void enableStormPrevention(Uint8 portnum) {
	Uint8 *controlPointer;

	if (portnum > HWPORT1) {
		return;
	}

	controlBMcast[portnum].suppressionEnabled = 1;

	if(portnum == HWPORT0) {
		controlPointer = (Uint8*)(PRU0_DRAM_BASE_ADDRESS + STORM_PREVENTION_OFFSET);
	} else {
		controlPointer = (Uint8*)(PRU1_DRAM_BASE_ADDRESS + STORM_PREVENTION_OFFSET);
	}
	*(controlPointer) = controlBMcast[portnum].suppressionEnabled;
}
/**
* @brief   Reset the credits at the end of time period, this time period is common to both broadcast and multicast packets
*
* @retval none
*/
void resetStormPreventionCounter() {
	Uint32 *controlPointer;
	Uint32 controlWord;

	if(controlBMcast[HWPORT0].suppressionEnabled) {
		controlPointer = (Uint32*)(PRU0_DRAM_BASE_ADDRESS + STORM_PREVENTION_OFFSET);
		controlWord = controlBMcast[HWPORT0].suppressionEnabled | (controlBMcast[HWPORT0].credits<<8);
		*(controlPointer) = controlWord;
	}
	if(controlBMcast[HWPORT1].suppressionEnabled) {
		controlPointer = (Uint32*)(PRU1_DRAM_BASE_ADDRESS + STORM_PREVENTION_OFFSET);
		controlWord = controlBMcast[HWPORT1].suppressionEnabled | (controlBMcast[HWPORT1].credits<<8);
		*(controlPointer) = controlWord;
	}

}
/**
* @brief   returns true if storm prevention is enabled
*
* @param portNum 0/1
*
* @retval Status. 1 if storm prevention is enabled on any port
*/
inline Uint8 ifStormPreventionEnabled(Uint8 portNum) {
	return controlBMcast[portNum].suppressionEnabled;
}

