| #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; |
| } |