diff options
Diffstat (limited to 'drivers/staging/bcm/led_control.c')
-rw-r--r-- | drivers/staging/bcm/led_control.c | 1006 |
1 files changed, 1006 insertions, 0 deletions
diff --git a/drivers/staging/bcm/led_control.c b/drivers/staging/bcm/led_control.c new file mode 100644 index 0000000..0d07664 --- /dev/null +++ b/drivers/staging/bcm/led_control.c @@ -0,0 +1,1006 @@ +#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; +} + +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; +} + +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; +} + + + +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> +//----------------------------------------------------------------------------- + +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> +//----------------------------------------------------------------------------- + +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() */ + +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; +} + + +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 +// +//----------------------------------------------------------------------------- + +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; +} +//----------------------------------------------------------------------------- + +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 ; +} +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; +} |