#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; UCHAR GPIO_Array[NUM_OF_LEDS+1]; /*Array to store GPIO numbers from EEPROM*/ 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; }