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