- 根目录:
- drivers
- staging
- bcm
- led_control.c
#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 = Adapter->dev->stats.tx_packets;
Initial_num_of_packts_rx = Adapter->dev->stats.rx_packets;
/* 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)) {
timeout = 50;
/*
* 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 = Adapter->dev->stats.tx_packets;
Final_num_of_packts_rx = Adapter->dev->stats.rx_packets;
rate_of_transfer_tx = Final_num_of_packts_tx -
Initial_num_of_packts_tx;
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 = kmalloc(usParamLen, GFP_KERNEL);
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:
kfree(puBuffer);
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;
/* Array to store GPIO numbers from EEPROM */
UCHAR GPIO_Array[NUM_OF_LEDS+1];
UINT uiIndex = 0;
UINT uiNum_of_LED_Type = 0;
PUCHAR puCFGData = NULL;
UCHAR bData = 0;
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;
}
/*
* 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;
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 (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; */
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;
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:
/*
* 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:
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;
}