#include "headers.h"

#define STATUS_IMAGE_CHECKSUM_MISMATCH -199
#define EVENT_SIGNALED 1

static B_UINT16 CFG_CalculateChecksum(B_UINT8 *pu8Buffer, B_UINT32 u32Size)
{
	B_UINT16 	u16CheckSum=0;
	while(u32Size--) {
		u16CheckSum += (B_UINT8)~(*pu8Buffer);
	    pu8Buffer++;
	}
	return u16CheckSum;
}
BOOLEAN IsReqGpioIsLedInNVM(PMINI_ADAPTER Adapter, UINT gpios)
{
	INT Status ;
	Status = (Adapter->gpioBitMap & gpios) ^ gpios ;
	if(Status)
		return FALSE;
	else
		return TRUE;
}

static INT LED_Blink(PMINI_ADAPTER Adapter, UINT GPIO_Num, UCHAR uiLedIndex, ULONG timeout, INT num_of_time, LedEventInfo_t currdriverstate)
{
	int Status = STATUS_SUCCESS;
	BOOLEAN bInfinite = FALSE;

	/*Check if num_of_time is -ve. If yes, blink led in infinite loop*/
	if(num_of_time < 0)
	{
		bInfinite = TRUE;
		num_of_time = 1;
	}
	while(num_of_time)
	{

		if(currdriverstate == Adapter->DriverState)
			TURN_ON_LED(GPIO_Num, uiLedIndex);

		/*Wait for timeout after setting on the LED*/
		Status = wait_event_interruptible_timeout(Adapter->LEDInfo.notify_led_event,
					currdriverstate != Adapter->DriverState || kthread_should_stop(),
					msecs_to_jiffies(timeout));

		if(kthread_should_stop())
		{
			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL, "Led thread got signal to exit..hence exiting");
			Adapter->LEDInfo.led_thread_running= BCM_LED_THREAD_DISABLED;
			TURN_OFF_LED(GPIO_Num, uiLedIndex);
			Status=EVENT_SIGNALED;
			break;
		}
		if(Status)
		{
			TURN_OFF_LED(GPIO_Num, uiLedIndex);
			Status=EVENT_SIGNALED;
			break;
		}

		TURN_OFF_LED(GPIO_Num, uiLedIndex);
		Status = wait_event_interruptible_timeout(Adapter->LEDInfo.notify_led_event,
					currdriverstate!= Adapter->DriverState || kthread_should_stop(),
					msecs_to_jiffies(timeout));
		if(bInfinite == FALSE)
			num_of_time--;
	}
	return Status;
}

static INT ScaleRateofTransfer(ULONG rate)
{
	if(rate <= 3)
		return rate;
	else if((rate > 3) && (rate <= 100))
		return 5;
	else if((rate > 100) && (rate <= 200))
		return 6;
	else if((rate > 200) && (rate <= 300))
		return 7;
	else if((rate > 300) && (rate <= 400))
		return 8;
	else if((rate > 400) && (rate <= 500))
		return 9;
	else if((rate > 500) && (rate <= 600))
		return 10;
	else
		return MAX_NUM_OF_BLINKS;
}



static INT LED_Proportional_Blink(PMINI_ADAPTER Adapter, UCHAR GPIO_Num_tx,
		UCHAR uiTxLedIndex, UCHAR GPIO_Num_rx, UCHAR uiRxLedIndex, LedEventInfo_t currdriverstate)
{
	/* Initial values of TX and RX packets*/
	ULONG64 Initial_num_of_packts_tx = 0, Initial_num_of_packts_rx = 0;
	/*values of TX and RX packets after 1 sec*/
	ULONG64 Final_num_of_packts_tx = 0, Final_num_of_packts_rx = 0;
	/*Rate of transfer of Tx and Rx in 1 sec*/
	ULONG64 rate_of_transfer_tx = 0, rate_of_transfer_rx = 0;
	int Status = STATUS_SUCCESS;
	INT num_of_time = 0, num_of_time_tx = 0, num_of_time_rx = 0;
	UINT remDelay = 0;
	BOOLEAN bBlinkBothLED = TRUE;
	//UINT GPIO_num = DISABLE_GPIO_NUM;
	ulong timeout = 0;

	/*Read initial value of packets sent/received */
	Initial_num_of_packts_tx = atomic_read(&Adapter->TxTotalPacketCount);
	Initial_num_of_packts_rx = atomic_read(&Adapter->GoodRxPktCount);
	/*Scale the rate of transfer to no of blinks.*/
	num_of_time_tx= ScaleRateofTransfer((ULONG)rate_of_transfer_tx);
	num_of_time_rx= ScaleRateofTransfer((ULONG)rate_of_transfer_rx);

	while((Adapter->device_removed == FALSE))
	{
		#if 0
		if(0 == num_of_time_tx && 0 == num_of_time_rx)
		{
			timeout = 1000;
			Status = wait_event_interruptible_timeout(Adapter->LEDInfo.notify_led_event,
				currdriverstate!= Adapter->DriverState || kthread_should_stop(),
				msecs_to_jiffies (timeout));
			if(kthread_should_stop())
			{
				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL, "Led thread got signal to exit..hence exiting");
				Adapter->LEDInfo.led_thread_running= BCM_LED_THREAD_DISABLED;
				return EVENT_SIGNALED;
			}
			if(Status)
				return EVENT_SIGNALED;

		}
		#endif

		timeout = 50;
		#if 0
		/*Turn on LED if Tx is high bandwidth*/
		if(num_of_time_tx > MAX_NUM_OF_BLINKS)
		{
			TURN_ON_LED(1<<GPIO_Num_tx, uiTxLedIndex);
			num_of_time_tx = 0;
			bBlinkBothLED = FALSE;
			num_of_time = num_of_time_rx;
		}
			/*Turn on LED if Rx is high bandwidth*/
		if(num_of_time_rx > MAX_NUM_OF_BLINKS)
		{
			TURN_ON_LED(1<<GPIO_Num_rx, uiRxLedIndex);
			num_of_time_rx = 0;
			bBlinkBothLED = FALSE;
			num_of_time = num_of_time_tx;
		}
		#endif
		/*Blink Tx and Rx LED when both Tx and Rx is in normal bandwidth*/
		if(bBlinkBothLED)
		{
			/*Assign minimum number of blinks of either Tx or Rx.*/
			if(num_of_time_tx > num_of_time_rx)
				num_of_time = num_of_time_rx;
			else
				num_of_time = num_of_time_tx;
			if(num_of_time > 0)
			{
				/*Blink both Tx and Rx LEDs*/
				if(LED_Blink(Adapter, 1<<GPIO_Num_tx, uiTxLedIndex, timeout, num_of_time,currdriverstate)
							== EVENT_SIGNALED)
				{
					return EVENT_SIGNALED;
				}
				if(LED_Blink(Adapter, 1<<GPIO_Num_rx, uiRxLedIndex, timeout, num_of_time,currdriverstate)
							== EVENT_SIGNALED)
				{
					return EVENT_SIGNALED;
				}

			}

			if(num_of_time == num_of_time_tx)
			{
				/*Blink pending rate of Rx*/
				if(LED_Blink(Adapter, (1 << GPIO_Num_rx), uiRxLedIndex, timeout,
						num_of_time_rx-num_of_time,currdriverstate) == EVENT_SIGNALED)
				{
					return EVENT_SIGNALED;
				}
				num_of_time = num_of_time_rx;
			}
			else
			{
				/*Blink pending rate of Tx*/
				if(LED_Blink(Adapter, 1<<GPIO_Num_tx, uiTxLedIndex, timeout,
					num_of_time_tx-num_of_time,currdriverstate) == EVENT_SIGNALED)
				{
					return EVENT_SIGNALED;
				}
				num_of_time = num_of_time_tx;
			}
		}
		else
		{
			if(num_of_time == num_of_time_tx)
			{
				/*Blink pending rate of Rx*/
				if(LED_Blink(Adapter, 1<<GPIO_Num_tx, uiTxLedIndex, timeout, num_of_time,currdriverstate)
							== EVENT_SIGNALED)
				{
					return EVENT_SIGNALED;
				}
			}
			else
			{
				/*Blink pending rate of Tx*/
				if(LED_Blink(Adapter, 1<<GPIO_Num_rx, uiRxLedIndex, timeout,
						num_of_time,currdriverstate) == EVENT_SIGNALED)
				{
					return EVENT_SIGNALED;
				}
			}
		}
		/* If Tx/Rx rate is less than maximum blinks per second,
			 * wait till delay completes to 1 second
			 */
		remDelay = MAX_NUM_OF_BLINKS - num_of_time;
		if(remDelay > 0)
		{
			timeout= 100 * remDelay;
			Status = wait_event_interruptible_timeout(Adapter->LEDInfo.notify_led_event,
						currdriverstate!= Adapter->DriverState ||kthread_should_stop() ,
						msecs_to_jiffies (timeout));

			if(kthread_should_stop())
			{
				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL, "Led thread got signal to exit..hence exiting");
				Adapter->LEDInfo.led_thread_running= BCM_LED_THREAD_DISABLED;
				return EVENT_SIGNALED;
			}
			if(Status)
				return EVENT_SIGNALED;
		}

		/*Turn off both Tx and Rx LEDs before next second*/
		TURN_OFF_LED(1<<GPIO_Num_tx, uiTxLedIndex);
		TURN_OFF_LED(1<<GPIO_Num_rx, uiTxLedIndex);

		/*
 		 * Read the Tx & Rx packets transmission after 1 second and
 		 * calculate rate of transfer
 		 */
		Final_num_of_packts_tx = atomic_read(&Adapter->TxTotalPacketCount);
		rate_of_transfer_tx = Final_num_of_packts_tx - Initial_num_of_packts_tx;
		Final_num_of_packts_rx = atomic_read(&Adapter->GoodRxPktCount);
		rate_of_transfer_rx = Final_num_of_packts_rx - Initial_num_of_packts_rx;

		/*Read initial value of packets sent/received */
		Initial_num_of_packts_tx = Final_num_of_packts_tx;
		Initial_num_of_packts_rx = Final_num_of_packts_rx ;

		/*Scale the rate of transfer to no of blinks.*/
		num_of_time_tx= ScaleRateofTransfer((ULONG)rate_of_transfer_tx);
		num_of_time_rx= ScaleRateofTransfer((ULONG)rate_of_transfer_rx);

	}
	return Status;
}


//-----------------------------------------------------------------------------
// Procedure:   ValidateDSDParamsChecksum
//
// Description: Reads DSD Params and validates checkusm.
//
// Arguments:
//      Adapter - Pointer to Adapter structure.
//      ulParamOffset - Start offset of the DSD parameter to be read and validated.
//      usParamLen - Length of the DSD Parameter.
//
// Returns:
//  <OSAL_STATUS_CODE>
//-----------------------------------------------------------------------------

static INT ValidateDSDParamsChecksum(
													PMINI_ADAPTER Adapter,
													ULONG  ulParamOffset,
													USHORT usParamLen )
{
	INT Status = STATUS_SUCCESS;
	PUCHAR puBuffer 		    = NULL;
	USHORT usChksmOrg		    = 0;
	USHORT usChecksumCalculated = 0;

	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread:ValidateDSDParamsChecksum: 0x%lx 0x%X",ulParamOffset, usParamLen);

	puBuffer = OsalMemAlloc(usParamLen,"!MEM");
	if(!puBuffer)
	{
		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: ValidateDSDParamsChecksum Allocation failed");
		return -ENOMEM;

	}

    //
    //	Read the DSD data from the parameter offset.
    //
	if(STATUS_SUCCESS != BeceemNVMRead(Adapter,(PUINT)puBuffer,ulParamOffset,usParamLen))
	{
		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: ValidateDSDParamsChecksum BeceemNVMRead failed");
		Status=STATUS_IMAGE_CHECKSUM_MISMATCH;
		goto exit;
	}

	//
	//	Calculate the checksum of the data read from the DSD parameter.
	//
	usChecksumCalculated = CFG_CalculateChecksum(puBuffer,usParamLen);
	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: usCheckSumCalculated = 0x%x\n", usChecksumCalculated);

	//
	//	End of the DSD parameter will have a TWO bytes checksum stored in it. Read it and compare with the calculated
	//	Checksum.
	//
	if(STATUS_SUCCESS != BeceemNVMRead(Adapter,(PUINT)&usChksmOrg,ulParamOffset+usParamLen,2))
	{
		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: ValidateDSDParamsChecksum BeceemNVMRead failed");
		Status=STATUS_IMAGE_CHECKSUM_MISMATCH;
		goto exit;
	}
	usChksmOrg = ntohs(usChksmOrg);
	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: usChksmOrg = 0x%x", usChksmOrg);

	//
	//  	Compare the checksum calculated with the checksum read from DSD section
	//
	if(usChecksumCalculated ^ usChksmOrg)
	{
		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: ValidateDSDParamsChecksum: Checksums don't match");
		Status = STATUS_IMAGE_CHECKSUM_MISMATCH;
		goto exit;
	}

exit:
	if(puBuffer)
	{
		OsalMemFree(puBuffer, usParamLen);
	}
	return Status;
}


//-----------------------------------------------------------------------------
// Procedure:   ValidateHWParmStructure
//
// Description: Validates HW Parameters.
//
// Arguments:
//      Adapter - Pointer to Adapter structure.
//      ulHwParamOffset - Start offset of the HW parameter Section to be read and validated.
//
// Returns:
//  <OSAL_STATUS_CODE>
//-----------------------------------------------------------------------------

static INT ValidateHWParmStructure(PMINI_ADAPTER Adapter, ULONG ulHwParamOffset)
{

	INT Status = STATUS_SUCCESS ;
	USHORT HwParamLen = 0;
	// Add DSD start offset to the hwParamOffset to get the actual address.
	ulHwParamOffset += DSD_START_OFFSET;

	/*Read the Length of HW_PARAM structure*/
	BeceemNVMRead(Adapter,(PUINT)&HwParamLen,ulHwParamOffset,2);
	HwParamLen = ntohs(HwParamLen);
	if(0==HwParamLen || HwParamLen > Adapter->uiNVMDSDSize)
	{
		return STATUS_IMAGE_CHECKSUM_MISMATCH;
	}

	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL, "LED Thread:HwParamLen = 0x%x", HwParamLen);
	Status =ValidateDSDParamsChecksum(Adapter,ulHwParamOffset,HwParamLen);
	return Status;
} /* ValidateHWParmStructure() */

static int ReadLEDInformationFromEEPROM(PMINI_ADAPTER Adapter, UCHAR GPIO_Array[])
{
	int Status = STATUS_SUCCESS;

	ULONG  dwReadValue 		= 0;
	USHORT usHwParamData 	= 0;
	USHORT usEEPROMVersion  = 0;
	UCHAR  ucIndex 			= 0;
	UCHAR  ucGPIOInfo[32] 	= {0};

	BeceemNVMRead(Adapter,(PUINT)&usEEPROMVersion,EEPROM_VERSION_OFFSET,2);

	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"usEEPROMVersion: Minor:0x%X Major:0x%x",usEEPROMVersion&0xFF, ((usEEPROMVersion>>8)&0xFF));


	if(((usEEPROMVersion>>8)&0xFF) < EEPROM_MAP5_MAJORVERSION)
	{
		BeceemNVMRead(Adapter,(PUINT)&usHwParamData,EEPROM_HW_PARAM_POINTER_ADDRESS,2);
		usHwParamData = ntohs(usHwParamData);
		dwReadValue   = usHwParamData;
	}
	else
	{
		//
		// Validate Compatibility section and then read HW param if compatibility section is valid.
		//
		Status = ValidateDSDParamsChecksum(Adapter,
			                   DSD_START_OFFSET,
			                   COMPATIBILITY_SECTION_LENGTH_MAP5);

		if(Status != STATUS_SUCCESS)
		{
			return Status;
		}
		BeceemNVMRead(Adapter,(PUINT)&dwReadValue,EEPROM_HW_PARAM_POINTER_ADDRRES_MAP5,4);
		dwReadValue = ntohl(dwReadValue);
	}


	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: Start address of HW_PARAM structure = 0x%lx",dwReadValue);

	//
	// Validate if the address read out is within the DSD.
	// Adapter->uiNVMDSDSize gives whole DSD size inclusive of Autoinit.
	// lower limit should be above DSD_START_OFFSET and
	// upper limit should be below (Adapter->uiNVMDSDSize-DSD_START_OFFSET)
	//
	if(dwReadValue < DSD_START_OFFSET ||
	   dwReadValue > (Adapter->uiNVMDSDSize-DSD_START_OFFSET))
	{
		return STATUS_IMAGE_CHECKSUM_MISMATCH;
	}

	Status = ValidateHWParmStructure(Adapter, dwReadValue);
	if(Status){
		return Status;
	}

	/*
	  Add DSD_START_OFFSET to the offset read from the EEPROM.
	  This will give the actual start HW Parameters start address.
	  To read GPIO section, add GPIO offset further.
	*/

	dwReadValue += DSD_START_OFFSET; // = start address of hw param section.
	dwReadValue += GPIO_SECTION_START_OFFSET; // = GPIO start offset within HW Param section.

	/* Read the GPIO values for 32 GPIOs from EEPROM and map the function
 	 * number to GPIO pin number to GPIO_Array
 	 */
	BeceemNVMRead(Adapter, (UINT *)ucGPIOInfo,dwReadValue,32);
	for(ucIndex = 0; ucIndex < 32; ucIndex++)
	 {

		 switch(ucGPIOInfo[ucIndex])
			{
				case RED_LED:
				{
				 	GPIO_Array[RED_LED] = ucIndex;
				 	Adapter->gpioBitMap |= (1<<ucIndex);
					break;
				}
				case BLUE_LED:
				{
					GPIO_Array[BLUE_LED] = ucIndex;
					Adapter->gpioBitMap |= (1<<ucIndex);
					break;
				}
				case YELLOW_LED:
				{
					 GPIO_Array[YELLOW_LED] = ucIndex;
					 Adapter->gpioBitMap |= (1<<ucIndex);
					 break;
				}
				case GREEN_LED:
				{
					GPIO_Array[GREEN_LED] = ucIndex;
				 	Adapter->gpioBitMap |= (1<<ucIndex);
					break;
				}
				default:
					break;
			}

		}
		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"GPIO's bit map correspond to LED :0x%X",Adapter->gpioBitMap);
	 return Status;
}


static int ReadConfigFileStructure(PMINI_ADAPTER Adapter, BOOLEAN *bEnableThread)
{
	int Status = STATUS_SUCCESS;
	UCHAR GPIO_Array[NUM_OF_LEDS+1]; /*Array to store GPIO numbers from EEPROM*/
#ifndef BCM_SHM_INTERFACE
	UINT uiIndex = 0;
	UINT uiNum_of_LED_Type = 0;
	PUCHAR puCFGData	= NULL;
	UCHAR bData = 0;
#endif
	memset(GPIO_Array, DISABLE_GPIO_NUM, NUM_OF_LEDS+1);

	if(!Adapter->pstargetparams || IS_ERR(Adapter->pstargetparams))
	{
		BCM_DEBUG_PRINT (Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL, "Target Params not Avail.\n");
		return -ENOENT;
	}

	/*Populate GPIO_Array with GPIO numbers for LED functions*/
	/*Read the GPIO numbers from EEPROM*/
	Status = ReadLEDInformationFromEEPROM(Adapter, GPIO_Array);
	if(Status == STATUS_IMAGE_CHECKSUM_MISMATCH)
	{
		*bEnableThread = FALSE;
		return STATUS_SUCCESS;
	}
	else if(Status)
	{
		*bEnableThread = FALSE;
		return Status;
	}
#ifdef BCM_SHM_INTERFACE
	*bEnableThread = FALSE;
	return Status ;
#else
  /*
     * CONFIG file read successfully. Deallocate the memory of
     * uiFileNameBufferSize
     */
	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: Config file read successfully\n");
	puCFGData = (PUCHAR) &Adapter->pstargetparams->HostDrvrConfig1;

	/*
 	 * Offset for HostDrvConfig1, HostDrvConfig2, HostDrvConfig3 which
 	 * will have the information of LED type, LED on state for different
 	 * driver state and LED blink state.
 	 */

	for(uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++)
	{
		bData = *puCFGData;

		/*Check Bit 8 for polarity. If it is set, polarity is reverse polarity*/
		if(bData & 0x80)
		{
			Adapter->LEDInfo.LEDState[uiIndex].BitPolarity = 0;
			/*unset the bit 8*/
			bData = bData & 0x7f;
		}

		Adapter->LEDInfo.LEDState[uiIndex].LED_Type = bData;
		if(bData <= NUM_OF_LEDS)
			Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num = GPIO_Array[bData];
		else
			Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num = DISABLE_GPIO_NUM;

		puCFGData++;
		bData = *puCFGData;
		Adapter->LEDInfo.LEDState[uiIndex].LED_On_State = bData;
		puCFGData++;
		bData = *puCFGData;
		Adapter->LEDInfo.LEDState[uiIndex].LED_Blink_State= bData;
		puCFGData++;
	}

	/*Check if all the LED settings are disabled. If it is disabled, dont launch the LED control thread.*/
	for(uiIndex = 0; uiIndex<NUM_OF_LEDS; uiIndex++)
	{
		if((Adapter->LEDInfo.LEDState[uiIndex].LED_Type == DISABLE_GPIO_NUM) ||
	 		(Adapter->LEDInfo.LEDState[uiIndex].LED_Type == 0x7f) ||
			(Adapter->LEDInfo.LEDState[uiIndex].LED_Type == 0))
			uiNum_of_LED_Type++;
	}
	if(uiNum_of_LED_Type >= NUM_OF_LEDS)
		*bEnableThread = FALSE;
#endif

#if 0
	for(uiIndex=0; uiIndex<NUM_OF_LEDS; uiIndex++)
	{
		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LEDState[%d].LED_Type = %x\n", uiIndex,
			Adapter->LEDInfo.LEDState[uiIndex].LED_Type);
		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LEDState[%d].LED_On_State = %x\n", uiIndex,
			Adapter->LEDInfo.LEDState[uiIndex].LED_On_State);
		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LEDState[%d].LED_Blink_State = %x\n", uiIndex,
			Adapter->LEDInfo.LEDState[uiIndex].LED_Blink_State);
		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LEDState[%d].GPIO_Num = %x\n", uiIndex,
			Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num);
	}
	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: Polarity = %d\n",
			Adapter->LEDInfo.BitPolarty);
#endif
	return Status;
}
//--------------------------------------------------------------------------
// Procedure:   LedGpioInit
//
// Description: Initializes LED GPIOs. Makes the LED GPIOs to OUTPUT mode and make the
//			  initial state to be OFF.
//
// Arguments:
//      Adapter - Pointer to MINI_ADAPTER structure.
//
// Returns: VOID
//
//-----------------------------------------------------------------------------

static VOID LedGpioInit(PMINI_ADAPTER Adapter)
{
	UINT uiResetValue = 0;
	UINT uiIndex      = 0;

	/* Set all LED GPIO Mode to output mode */
	if(rdmalt(Adapter, GPIO_MODE_REGISTER, &uiResetValue, sizeof(uiResetValue)) <0)
		BCM_DEBUG_PRINT (Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: RDM Failed\n");
	for(uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++)
	{
		if(Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num != DISABLE_GPIO_NUM)
			uiResetValue |= (1 << Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num);
		TURN_OFF_LED(1<<Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num,uiIndex);
	}
	if(wrmalt(Adapter, GPIO_MODE_REGISTER, &uiResetValue, sizeof(uiResetValue)) < 0)
		BCM_DEBUG_PRINT (Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: WRM Failed\n");

	Adapter->LEDInfo.bIdle_led_off =  FALSE;
}
//-----------------------------------------------------------------------------

static INT BcmGetGPIOPinInfo(PMINI_ADAPTER Adapter, UCHAR *GPIO_num_tx, UCHAR *GPIO_num_rx ,UCHAR *uiLedTxIndex, UCHAR *uiLedRxIndex,LedEventInfo_t currdriverstate)
{
	UINT uiIndex = 0;

	*GPIO_num_tx = DISABLE_GPIO_NUM;
	*GPIO_num_rx = DISABLE_GPIO_NUM;

	for(uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++)
	{

		if((currdriverstate == NORMAL_OPERATION)||
			(currdriverstate == IDLEMODE_EXIT)||
			(currdriverstate == FW_DOWNLOAD))
		{
			if(Adapter->LEDInfo.LEDState[uiIndex].LED_Blink_State & currdriverstate)
			{
				if(Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num != DISABLE_GPIO_NUM)
				{
					if(*GPIO_num_tx == DISABLE_GPIO_NUM)
					{
						*GPIO_num_tx = Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num;
						*uiLedTxIndex = uiIndex;
					}
					else
					{
						*GPIO_num_rx = Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num;
						*uiLedRxIndex = uiIndex;
					}
				}
			}
		}
		else
		{
			if(Adapter->LEDInfo.LEDState[uiIndex].LED_On_State & currdriverstate)
			{
				if(Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num != DISABLE_GPIO_NUM)
				{
					*GPIO_num_tx = Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num;
					*uiLedTxIndex = uiIndex;
				}
			}
		}
	}
	return STATUS_SUCCESS ;
}
static VOID LEDControlThread(PMINI_ADAPTER Adapter)
{
	UINT uiIndex = 0;
	UCHAR GPIO_num = 0;
	UCHAR uiLedIndex = 0 ;
	UINT uiResetValue = 0;
	LedEventInfo_t currdriverstate = 0;
	ulong timeout = 0;

	INT Status = 0;

	UCHAR  dummyGPIONum = 0;
	UCHAR  dummyIndex = 0;

	//currdriverstate = Adapter->DriverState;
	Adapter->LEDInfo.bIdleMode_tx_from_host = FALSE;

	/*Wait till event is triggered*/
	//wait_event(Adapter->LEDInfo.notify_led_event,
			//	currdriverstate!= Adapter->DriverState);

	GPIO_num = DISABLE_GPIO_NUM ;

	while(TRUE)
	{
		/*Wait till event is triggered*/
		if( (GPIO_num == DISABLE_GPIO_NUM)
						||
			((currdriverstate != FW_DOWNLOAD) &&
			 (currdriverstate != NORMAL_OPERATION) &&
			 (currdriverstate != LOWPOWER_MODE_ENTER))
			 			||
			 (currdriverstate == LED_THREAD_INACTIVE)	)
		{
			Status = wait_event_interruptible(Adapter->LEDInfo.notify_led_event,
				currdriverstate != Adapter->DriverState || kthread_should_stop());
		}

		if(kthread_should_stop() || Adapter->device_removed )
		{
			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL, "Led thread got signal to exit..hence exiting");
			Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_DISABLED;
			TURN_OFF_LED(1<<GPIO_num, uiLedIndex);
			return ;//STATUS_FAILURE;
		}
	#if 0
		if(Adapter->device_removed)
		{
			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"Device removed hence exiting from Led Thread..");
			return ; //-ENODEV;
		}
	#endif
		#if 0
		if((GPIO_num != DISABLE_GPIO_NUM) &&
			((currdriverstate != FW_DOWNLOAD) &&
			(currdriverstate != NORMAL_OPERATION) &&
			(currdriverstate != IDLEMODE_EXIT)))
			TURN_OFF_LED(1<<GPIO_num, uiLedIndex);
		#endif

		if(GPIO_num != DISABLE_GPIO_NUM)
		{
			TURN_OFF_LED(1<<GPIO_num, uiLedIndex);
		}

		if(Adapter->LEDInfo.bLedInitDone == FALSE)
		{
			LedGpioInit(Adapter);
			Adapter->LEDInfo.bLedInitDone = TRUE;
		}

		switch(Adapter->DriverState)
		{
			case DRIVER_INIT:
			{
				currdriverstate = DRIVER_INIT;//Adapter->DriverState;
	#if 0
				LedGpioInit(Adapter);
				Adapter->LEDInfo.bLedInitDone = TRUE;
	#endif
				BcmGetGPIOPinInfo(Adapter, &GPIO_num, &dummyGPIONum, &uiLedIndex, &dummyIndex, currdriverstate);

				if(GPIO_num  != DISABLE_GPIO_NUM)
				{
					TURN_ON_LED(1<<GPIO_num, uiLedIndex);
				}
			}
			break;
			case FW_DOWNLOAD:
			{
				//BCM_DEBUG_PRINT (Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: FW_DN_DONE called\n");
				currdriverstate = FW_DOWNLOAD;
			#if 0
				if(Adapter->LEDInfo.bLedInitDone == FALSE)
				{
					LedGpioInit(Adapter);
					Adapter->LEDInfo.bLedInitDone = TRUE;
				}
			#endif
				BcmGetGPIOPinInfo(Adapter, &GPIO_num, &dummyGPIONum,  &uiLedIndex, &dummyIndex, currdriverstate);

				if(GPIO_num != DISABLE_GPIO_NUM)
				{
					timeout = 50;
					LED_Blink(Adapter, 1<<GPIO_num, uiLedIndex, timeout, -1,currdriverstate);
				}
			}
			break;
			case FW_DOWNLOAD_DONE:
			{
				currdriverstate = FW_DOWNLOAD_DONE;
				BcmGetGPIOPinInfo(Adapter, &GPIO_num, &dummyGPIONum, &uiLedIndex, &dummyIndex,currdriverstate);
				if(GPIO_num != DISABLE_GPIO_NUM)
				{
					TURN_ON_LED(1<<GPIO_num, uiLedIndex);
				}
			}
			break;

			case SHUTDOWN_EXIT:
			#if 0
			if(Adapter->ulPowerSaveMode == DEVICE_POWERSAVE_MODE_AS_PMU_SHUTDOWN)
			{
				LedGpioInit(Adapter);
			}
			#endif
			//no break, continue to NO_NETWORK_ENTRY state as well.

			case NO_NETWORK_ENTRY:
			{
				currdriverstate = NO_NETWORK_ENTRY;
				BcmGetGPIOPinInfo(Adapter, &GPIO_num, &dummyGPIONum, &uiLedIndex,&dummyGPIONum,currdriverstate);
				if(GPIO_num != DISABLE_GPIO_NUM)
				{
					TURN_ON_LED(1<<GPIO_num, uiLedIndex);
				}
			}
			break;
			case NORMAL_OPERATION:
			{
				UCHAR GPIO_num_tx = DISABLE_GPIO_NUM;
				UCHAR GPIO_num_rx = DISABLE_GPIO_NUM;
				UCHAR uiLEDTx = 0;
				UCHAR uiLEDRx = 0;
				currdriverstate = NORMAL_OPERATION;
				Adapter->LEDInfo.bIdle_led_off =  FALSE;

				BcmGetGPIOPinInfo(Adapter, &GPIO_num_tx, &GPIO_num_rx, &uiLEDTx,&uiLEDRx,currdriverstate);
				if((GPIO_num_tx == DISABLE_GPIO_NUM) && (GPIO_num_rx == DISABLE_GPIO_NUM))
				{
					GPIO_num = DISABLE_GPIO_NUM ;
				}
				else
				{
					/*If single LED is selected, use same for both Tx and Rx*/
					if(GPIO_num_tx == DISABLE_GPIO_NUM)
					{
						GPIO_num_tx = GPIO_num_rx;
						uiLEDTx = uiLEDRx;
					}
					else if(GPIO_num_rx == DISABLE_GPIO_NUM)
					{
						GPIO_num_rx = GPIO_num_tx;
						uiLEDRx = uiLEDTx;
					}
				/*Blink the LED in proportionate to Tx and Rx transmissions.*/
					LED_Proportional_Blink(Adapter, GPIO_num_tx, uiLEDTx, GPIO_num_rx, uiLEDRx,currdriverstate);
				}
			}
			break;
			case LOWPOWER_MODE_ENTER:
			{
				currdriverstate  = LOWPOWER_MODE_ENTER;
				if( DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING == Adapter->ulPowerSaveMode)
				{
					/* Turn OFF all the LED */
					uiResetValue = 0;
					for(uiIndex =0; uiIndex < NUM_OF_LEDS; uiIndex++)
					{
						if(Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num != DISABLE_GPIO_NUM)
						TURN_OFF_LED((1<<Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num),uiIndex);
					}

				}
				/* Turn off LED And WAKE-UP for Sendinf IDLE mode ACK */
				Adapter->LEDInfo.bLedInitDone = FALSE;
				Adapter->LEDInfo.bIdle_led_off =  TRUE;
				wake_up(&Adapter->LEDInfo.idleModeSyncEvent);
				GPIO_num = DISABLE_GPIO_NUM;
				break;
			}
			case IDLEMODE_CONTINUE:
			{
				currdriverstate = IDLEMODE_CONTINUE;
				GPIO_num = DISABLE_GPIO_NUM;
			}
			break;
			case IDLEMODE_EXIT:
			{
#if 0
				UCHAR GPIO_num_tx = DISABLE_GPIO_NUM;
				UCHAR GPIO_num_rx = DISABLE_GPIO_NUM;
				UCHAR uiTxLedIndex = 0;
				UCHAR uiRxLedIndex = 0;

				currdriverstate  = IDLEMODE_EXIT;
				if(DEVICE_POWERSAVE_MODE_AS_PMU_SHUTDOWN == Adapter->ulPowerSaveMode)
				{
					LedGpioInit(Adapter);
				}
				BcmGetGPIOPinInfo(Adapter, &GPIO_num_tx, &GPIO_num_rx, &uiTxLedIndex,&uiRxLedIndex,currdriverstate);

				Adapter->LEDInfo.bIdle_led_off =  FALSE;

				if((GPIO_num_tx == DISABLE_GPIO_NUM) && (GPIO_num_rx == DISABLE_GPIO_NUM))
				{
					GPIO_num = DISABLE_GPIO_NUM ;
				}
				else
				{
					timeout = 50;
					if(Adapter->LEDInfo.bIdleMode_tx_from_host)
						LED_Blink(Adapter, 1<<GPIO_num_tx, uiTxLedIndex, timeout, -1,currdriverstate);
					else
						LED_Blink(Adapter, 1<<GPIO_num_rx, uiRxLedIndex, timeout, -1,currdriverstate);
				}
#endif
			}
			break;
			case DRIVER_HALT:
			{
				currdriverstate = DRIVER_HALT;
				GPIO_num = DISABLE_GPIO_NUM;
				for(uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++)
				{
					if(Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num !=
						DISABLE_GPIO_NUM)
						TURN_OFF_LED((1<<Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num),uiIndex);
				}
				//Adapter->DriverState = DRIVER_INIT;
			}
			break;
			case LED_THREAD_INACTIVE :
			{
				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"InActivating LED thread...");
				currdriverstate = LED_THREAD_INACTIVE;
				Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_RUNNING_INACTIVELY ;
				Adapter->LEDInfo.bLedInitDone = FALSE ;
				//disable ALL LED
				for(uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++)
				{
					if(Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num !=
						DISABLE_GPIO_NUM)
						TURN_OFF_LED((1<<Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num),uiIndex);
				}
			}
			break;
			case LED_THREAD_ACTIVE :
			{
				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"Activating LED thread again...");
				if(Adapter->LinkUpStatus == FALSE)
					Adapter->DriverState = NO_NETWORK_ENTRY;
				else
					Adapter->DriverState = NORMAL_OPERATION;

				Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_RUNNING_ACTIVELY ;
			}
			break;
			//return;
			default:
				break;
		}
	}
	Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_DISABLED;
}

int InitLedSettings(PMINI_ADAPTER Adapter)
{
	int Status = STATUS_SUCCESS;
	BOOLEAN bEnableThread = TRUE;
	UCHAR uiIndex = 0;

	/*Initially set BitPolarity to normal polarity. The bit 8 of LED type
 * 	  is used to change the polarity of the LED.*/

	for(uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) {
		Adapter->LEDInfo.LEDState[uiIndex].BitPolarity = 1;
	}

	/*Read the LED settings of CONFIG file and map it to GPIO numbers in EEPROM*/
	Status = ReadConfigFileStructure(Adapter, &bEnableThread);
	if(STATUS_SUCCESS != Status)
	{
		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: FAILED in ReadConfigFileStructure\n");
		return Status;
	}

	if(Adapter->LEDInfo.led_thread_running)
	{
		if(bEnableThread)
			;
		else
		{
			Adapter->DriverState = DRIVER_HALT;
			wake_up(&Adapter->LEDInfo.notify_led_event);
			Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_DISABLED;
		}

	}

	else if(bEnableThread)
	{
		/*Create secondary thread to handle the LEDs*/
		init_waitqueue_head(&Adapter->LEDInfo.notify_led_event);
		init_waitqueue_head(&Adapter->LEDInfo.idleModeSyncEvent);
		Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_RUNNING_ACTIVELY;
		Adapter->LEDInfo.bIdle_led_off =  FALSE;
		Adapter->LEDInfo.led_cntrl_threadid = kthread_run((int (*)(void *))
            LEDControlThread, Adapter, "led_control_thread");
		if(IS_ERR(Adapter->LEDInfo.led_cntrl_threadid))
    	{
        	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL, "Not able to spawn Kernel Thread\n");
			Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_DISABLED;
        	return PTR_ERR(Adapter->LEDInfo.led_cntrl_threadid);
    	}
	}
	return Status;
}
