beceem: remove ifdef's
[pandora-kernel.git] / drivers / staging / bcm / led_control.c
1 #include "headers.h"
2
3 #define STATUS_IMAGE_CHECKSUM_MISMATCH -199
4 #define EVENT_SIGNALED 1
5
6 static B_UINT16 CFG_CalculateChecksum(B_UINT8 *pu8Buffer, B_UINT32 u32Size)
7 {
8         B_UINT16        u16CheckSum=0;
9         while(u32Size--) {
10                 u16CheckSum += (B_UINT8)~(*pu8Buffer);
11             pu8Buffer++;
12         }
13         return u16CheckSum;
14 }
15 BOOLEAN IsReqGpioIsLedInNVM(PMINI_ADAPTER Adapter, UINT gpios)
16 {
17         INT Status ;
18         Status = (Adapter->gpioBitMap & gpios) ^ gpios ;
19         if(Status)
20                 return FALSE;
21         else
22                 return TRUE;
23 }
24
25 static INT LED_Blink(PMINI_ADAPTER Adapter, UINT GPIO_Num, UCHAR uiLedIndex, ULONG timeout, INT num_of_time, LedEventInfo_t currdriverstate)
26 {
27         int Status = STATUS_SUCCESS;
28         BOOLEAN bInfinite = FALSE;
29
30         /*Check if num_of_time is -ve. If yes, blink led in infinite loop*/
31         if(num_of_time < 0)
32         {
33                 bInfinite = TRUE;
34                 num_of_time = 1;
35         }
36         while(num_of_time)
37         {
38
39                 if(currdriverstate == Adapter->DriverState)
40                         TURN_ON_LED(GPIO_Num, uiLedIndex);
41
42                 /*Wait for timeout after setting on the LED*/
43                 Status = wait_event_interruptible_timeout(Adapter->LEDInfo.notify_led_event,
44                                         currdriverstate != Adapter->DriverState || kthread_should_stop(),
45                                         msecs_to_jiffies(timeout));
46
47                 if(kthread_should_stop())
48                 {
49                         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL, "Led thread got signal to exit..hence exiting");
50                         Adapter->LEDInfo.led_thread_running= BCM_LED_THREAD_DISABLED;
51                         TURN_OFF_LED(GPIO_Num, uiLedIndex);
52                         Status=EVENT_SIGNALED;
53                         break;
54                 }
55                 if(Status)
56                 {
57                         TURN_OFF_LED(GPIO_Num, uiLedIndex);
58                         Status=EVENT_SIGNALED;
59                         break;
60                 }
61
62                 TURN_OFF_LED(GPIO_Num, uiLedIndex);
63                 Status = wait_event_interruptible_timeout(Adapter->LEDInfo.notify_led_event,
64                                         currdriverstate!= Adapter->DriverState || kthread_should_stop(),
65                                         msecs_to_jiffies(timeout));
66                 if(bInfinite == FALSE)
67                         num_of_time--;
68         }
69         return Status;
70 }
71
72 static INT ScaleRateofTransfer(ULONG rate)
73 {
74         if(rate <= 3)
75                 return rate;
76         else if((rate > 3) && (rate <= 100))
77                 return 5;
78         else if((rate > 100) && (rate <= 200))
79                 return 6;
80         else if((rate > 200) && (rate <= 300))
81                 return 7;
82         else if((rate > 300) && (rate <= 400))
83                 return 8;
84         else if((rate > 400) && (rate <= 500))
85                 return 9;
86         else if((rate > 500) && (rate <= 600))
87                 return 10;
88         else
89                 return MAX_NUM_OF_BLINKS;
90 }
91
92
93
94 static INT LED_Proportional_Blink(PMINI_ADAPTER Adapter, UCHAR GPIO_Num_tx,
95                 UCHAR uiTxLedIndex, UCHAR GPIO_Num_rx, UCHAR uiRxLedIndex, LedEventInfo_t currdriverstate)
96 {
97         /* Initial values of TX and RX packets*/
98         ULONG64 Initial_num_of_packts_tx = 0, Initial_num_of_packts_rx = 0;
99         /*values of TX and RX packets after 1 sec*/
100         ULONG64 Final_num_of_packts_tx = 0, Final_num_of_packts_rx = 0;
101         /*Rate of transfer of Tx and Rx in 1 sec*/
102         ULONG64 rate_of_transfer_tx = 0, rate_of_transfer_rx = 0;
103         int Status = STATUS_SUCCESS;
104         INT num_of_time = 0, num_of_time_tx = 0, num_of_time_rx = 0;
105         UINT remDelay = 0;
106         BOOLEAN bBlinkBothLED = TRUE;
107         //UINT GPIO_num = DISABLE_GPIO_NUM;
108         ulong timeout = 0;
109
110         /*Read initial value of packets sent/received */
111         Initial_num_of_packts_tx = atomic_read(&Adapter->TxTotalPacketCount);
112         Initial_num_of_packts_rx = atomic_read(&Adapter->GoodRxPktCount);
113         /*Scale the rate of transfer to no of blinks.*/
114         num_of_time_tx= ScaleRateofTransfer((ULONG)rate_of_transfer_tx);
115         num_of_time_rx= ScaleRateofTransfer((ULONG)rate_of_transfer_rx);
116
117         while((Adapter->device_removed == FALSE))
118         {
119                 #if 0
120                 if(0 == num_of_time_tx && 0 == num_of_time_rx)
121                 {
122                         timeout = 1000;
123                         Status = wait_event_interruptible_timeout(Adapter->LEDInfo.notify_led_event,
124                                 currdriverstate!= Adapter->DriverState || kthread_should_stop(),
125                                 msecs_to_jiffies (timeout));
126                         if(kthread_should_stop())
127                         {
128                                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL, "Led thread got signal to exit..hence exiting");
129                                 Adapter->LEDInfo.led_thread_running= BCM_LED_THREAD_DISABLED;
130                                 return EVENT_SIGNALED;
131                         }
132                         if(Status)
133                                 return EVENT_SIGNALED;
134
135                 }
136                 #endif
137
138                 timeout = 50;
139                 #if 0
140                 /*Turn on LED if Tx is high bandwidth*/
141                 if(num_of_time_tx > MAX_NUM_OF_BLINKS)
142                 {
143                         TURN_ON_LED(1<<GPIO_Num_tx, uiTxLedIndex);
144                         num_of_time_tx = 0;
145                         bBlinkBothLED = FALSE;
146                         num_of_time = num_of_time_rx;
147                 }
148                         /*Turn on LED if Rx is high bandwidth*/
149                 if(num_of_time_rx > MAX_NUM_OF_BLINKS)
150                 {
151                         TURN_ON_LED(1<<GPIO_Num_rx, uiRxLedIndex);
152                         num_of_time_rx = 0;
153                         bBlinkBothLED = FALSE;
154                         num_of_time = num_of_time_tx;
155                 }
156                 #endif
157                 /*Blink Tx and Rx LED when both Tx and Rx is in normal bandwidth*/
158                 if(bBlinkBothLED)
159                 {
160                         /*Assign minimum number of blinks of either Tx or Rx.*/
161                         if(num_of_time_tx > num_of_time_rx)
162                                 num_of_time = num_of_time_rx;
163                         else
164                                 num_of_time = num_of_time_tx;
165                         if(num_of_time > 0)
166                         {
167                                 /*Blink both Tx and Rx LEDs*/
168                                 if(LED_Blink(Adapter, 1<<GPIO_Num_tx, uiTxLedIndex, timeout, num_of_time,currdriverstate)
169                                                         == EVENT_SIGNALED)
170                                 {
171                                         return EVENT_SIGNALED;
172                                 }
173                                 if(LED_Blink(Adapter, 1<<GPIO_Num_rx, uiRxLedIndex, timeout, num_of_time,currdriverstate)
174                                                         == EVENT_SIGNALED)
175                                 {
176                                         return EVENT_SIGNALED;
177                                 }
178
179                         }
180
181                         if(num_of_time == num_of_time_tx)
182                         {
183                                 /*Blink pending rate of Rx*/
184                                 if(LED_Blink(Adapter, (1 << GPIO_Num_rx), uiRxLedIndex, timeout,
185                                                 num_of_time_rx-num_of_time,currdriverstate) == EVENT_SIGNALED)
186                                 {
187                                         return EVENT_SIGNALED;
188                                 }
189                                 num_of_time = num_of_time_rx;
190                         }
191                         else
192                         {
193                                 /*Blink pending rate of Tx*/
194                                 if(LED_Blink(Adapter, 1<<GPIO_Num_tx, uiTxLedIndex, timeout,
195                                         num_of_time_tx-num_of_time,currdriverstate) == EVENT_SIGNALED)
196                                 {
197                                         return EVENT_SIGNALED;
198                                 }
199                                 num_of_time = num_of_time_tx;
200                         }
201                 }
202                 else
203                 {
204                         if(num_of_time == num_of_time_tx)
205                         {
206                                 /*Blink pending rate of Rx*/
207                                 if(LED_Blink(Adapter, 1<<GPIO_Num_tx, uiTxLedIndex, timeout, num_of_time,currdriverstate)
208                                                         == EVENT_SIGNALED)
209                                 {
210                                         return EVENT_SIGNALED;
211                                 }
212                         }
213                         else
214                         {
215                                 /*Blink pending rate of Tx*/
216                                 if(LED_Blink(Adapter, 1<<GPIO_Num_rx, uiRxLedIndex, timeout,
217                                                 num_of_time,currdriverstate) == EVENT_SIGNALED)
218                                 {
219                                         return EVENT_SIGNALED;
220                                 }
221                         }
222                 }
223                 /* If Tx/Rx rate is less than maximum blinks per second,
224                          * wait till delay completes to 1 second
225                          */
226                 remDelay = MAX_NUM_OF_BLINKS - num_of_time;
227                 if(remDelay > 0)
228                 {
229                         timeout= 100 * remDelay;
230                         Status = wait_event_interruptible_timeout(Adapter->LEDInfo.notify_led_event,
231                                                 currdriverstate!= Adapter->DriverState ||kthread_should_stop() ,
232                                                 msecs_to_jiffies (timeout));
233
234                         if(kthread_should_stop())
235                         {
236                                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL, "Led thread got signal to exit..hence exiting");
237                                 Adapter->LEDInfo.led_thread_running= BCM_LED_THREAD_DISABLED;
238                                 return EVENT_SIGNALED;
239                         }
240                         if(Status)
241                                 return EVENT_SIGNALED;
242                 }
243
244                 /*Turn off both Tx and Rx LEDs before next second*/
245                 TURN_OFF_LED(1<<GPIO_Num_tx, uiTxLedIndex);
246                 TURN_OFF_LED(1<<GPIO_Num_rx, uiTxLedIndex);
247
248                 /*
249                  * Read the Tx & Rx packets transmission after 1 second and
250                  * calculate rate of transfer
251                  */
252                 Final_num_of_packts_tx = atomic_read(&Adapter->TxTotalPacketCount);
253                 rate_of_transfer_tx = Final_num_of_packts_tx - Initial_num_of_packts_tx;
254                 Final_num_of_packts_rx = atomic_read(&Adapter->GoodRxPktCount);
255                 rate_of_transfer_rx = Final_num_of_packts_rx - Initial_num_of_packts_rx;
256
257                 /*Read initial value of packets sent/received */
258                 Initial_num_of_packts_tx = Final_num_of_packts_tx;
259                 Initial_num_of_packts_rx = Final_num_of_packts_rx ;
260
261                 /*Scale the rate of transfer to no of blinks.*/
262                 num_of_time_tx= ScaleRateofTransfer((ULONG)rate_of_transfer_tx);
263                 num_of_time_rx= ScaleRateofTransfer((ULONG)rate_of_transfer_rx);
264
265         }
266         return Status;
267 }
268
269
270 //-----------------------------------------------------------------------------
271 // Procedure:   ValidateDSDParamsChecksum
272 //
273 // Description: Reads DSD Params and validates checkusm.
274 //
275 // Arguments:
276 //      Adapter - Pointer to Adapter structure.
277 //      ulParamOffset - Start offset of the DSD parameter to be read and validated.
278 //      usParamLen - Length of the DSD Parameter.
279 //
280 // Returns:
281 //  <OSAL_STATUS_CODE>
282 //-----------------------------------------------------------------------------
283
284 static INT ValidateDSDParamsChecksum(
285                                                                                                         PMINI_ADAPTER Adapter,
286                                                                                                         ULONG  ulParamOffset,
287                                                                                                         USHORT usParamLen )
288 {
289         INT Status = STATUS_SUCCESS;
290         PUCHAR puBuffer                     = NULL;
291         USHORT usChksmOrg                   = 0;
292         USHORT usChecksumCalculated = 0;
293
294         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread:ValidateDSDParamsChecksum: 0x%lx 0x%X",ulParamOffset, usParamLen);
295
296         puBuffer = OsalMemAlloc(usParamLen,"!MEM");
297         if(!puBuffer)
298         {
299                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: ValidateDSDParamsChecksum Allocation failed");
300                 return -ENOMEM;
301
302         }
303
304     //
305     //  Read the DSD data from the parameter offset.
306     //
307         if(STATUS_SUCCESS != BeceemNVMRead(Adapter,(PUINT)puBuffer,ulParamOffset,usParamLen))
308         {
309                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: ValidateDSDParamsChecksum BeceemNVMRead failed");
310                 Status=STATUS_IMAGE_CHECKSUM_MISMATCH;
311                 goto exit;
312         }
313
314         //
315         //      Calculate the checksum of the data read from the DSD parameter.
316         //
317         usChecksumCalculated = CFG_CalculateChecksum(puBuffer,usParamLen);
318         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: usCheckSumCalculated = 0x%x\n", usChecksumCalculated);
319
320         //
321         //      End of the DSD parameter will have a TWO bytes checksum stored in it. Read it and compare with the calculated
322         //      Checksum.
323         //
324         if(STATUS_SUCCESS != BeceemNVMRead(Adapter,(PUINT)&usChksmOrg,ulParamOffset+usParamLen,2))
325         {
326                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: ValidateDSDParamsChecksum BeceemNVMRead failed");
327                 Status=STATUS_IMAGE_CHECKSUM_MISMATCH;
328                 goto exit;
329         }
330         usChksmOrg = ntohs(usChksmOrg);
331         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: usChksmOrg = 0x%x", usChksmOrg);
332
333         //
334         //      Compare the checksum calculated with the checksum read from DSD section
335         //
336         if(usChecksumCalculated ^ usChksmOrg)
337         {
338                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: ValidateDSDParamsChecksum: Checksums don't match");
339                 Status = STATUS_IMAGE_CHECKSUM_MISMATCH;
340                 goto exit;
341         }
342
343 exit:
344         if(puBuffer)
345         {
346                 OsalMemFree(puBuffer, usParamLen);
347         }
348         return Status;
349 }
350
351
352 //-----------------------------------------------------------------------------
353 // Procedure:   ValidateHWParmStructure
354 //
355 // Description: Validates HW Parameters.
356 //
357 // Arguments:
358 //      Adapter - Pointer to Adapter structure.
359 //      ulHwParamOffset - Start offset of the HW parameter Section to be read and validated.
360 //
361 // Returns:
362 //  <OSAL_STATUS_CODE>
363 //-----------------------------------------------------------------------------
364
365 static INT ValidateHWParmStructure(PMINI_ADAPTER Adapter, ULONG ulHwParamOffset)
366 {
367
368         INT Status = STATUS_SUCCESS ;
369         USHORT HwParamLen = 0;
370         // Add DSD start offset to the hwParamOffset to get the actual address.
371         ulHwParamOffset += DSD_START_OFFSET;
372
373         /*Read the Length of HW_PARAM structure*/
374         BeceemNVMRead(Adapter,(PUINT)&HwParamLen,ulHwParamOffset,2);
375         HwParamLen = ntohs(HwParamLen);
376         if(0==HwParamLen || HwParamLen > Adapter->uiNVMDSDSize)
377         {
378                 return STATUS_IMAGE_CHECKSUM_MISMATCH;
379         }
380
381         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL, "LED Thread:HwParamLen = 0x%x", HwParamLen);
382         Status =ValidateDSDParamsChecksum(Adapter,ulHwParamOffset,HwParamLen);
383         return Status;
384 } /* ValidateHWParmStructure() */
385
386 static int ReadLEDInformationFromEEPROM(PMINI_ADAPTER Adapter, UCHAR GPIO_Array[])
387 {
388         int Status = STATUS_SUCCESS;
389
390         ULONG  dwReadValue              = 0;
391         USHORT usHwParamData    = 0;
392         USHORT usEEPROMVersion  = 0;
393         UCHAR  ucIndex                  = 0;
394         UCHAR  ucGPIOInfo[32]   = {0};
395
396         BeceemNVMRead(Adapter,(PUINT)&usEEPROMVersion,EEPROM_VERSION_OFFSET,2);
397
398         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));
399
400
401         if(((usEEPROMVersion>>8)&0xFF) < EEPROM_MAP5_MAJORVERSION)
402         {
403                 BeceemNVMRead(Adapter,(PUINT)&usHwParamData,EEPROM_HW_PARAM_POINTER_ADDRESS,2);
404                 usHwParamData = ntohs(usHwParamData);
405                 dwReadValue   = usHwParamData;
406         }
407         else
408         {
409                 //
410                 // Validate Compatibility section and then read HW param if compatibility section is valid.
411                 //
412                 Status = ValidateDSDParamsChecksum(Adapter,
413                                            DSD_START_OFFSET,
414                                            COMPATIBILITY_SECTION_LENGTH_MAP5);
415
416                 if(Status != STATUS_SUCCESS)
417                 {
418                         return Status;
419                 }
420                 BeceemNVMRead(Adapter,(PUINT)&dwReadValue,EEPROM_HW_PARAM_POINTER_ADDRRES_MAP5,4);
421                 dwReadValue = ntohl(dwReadValue);
422         }
423
424
425         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: Start address of HW_PARAM structure = 0x%lx",dwReadValue);
426
427         //
428         // Validate if the address read out is within the DSD.
429         // Adapter->uiNVMDSDSize gives whole DSD size inclusive of Autoinit.
430         // lower limit should be above DSD_START_OFFSET and
431         // upper limit should be below (Adapter->uiNVMDSDSize-DSD_START_OFFSET)
432         //
433         if(dwReadValue < DSD_START_OFFSET ||
434            dwReadValue > (Adapter->uiNVMDSDSize-DSD_START_OFFSET))
435         {
436                 return STATUS_IMAGE_CHECKSUM_MISMATCH;
437         }
438
439         Status = ValidateHWParmStructure(Adapter, dwReadValue);
440         if(Status){
441                 return Status;
442         }
443
444         /*
445           Add DSD_START_OFFSET to the offset read from the EEPROM.
446           This will give the actual start HW Parameters start address.
447           To read GPIO section, add GPIO offset further.
448         */
449
450         dwReadValue += DSD_START_OFFSET; // = start address of hw param section.
451         dwReadValue += GPIO_SECTION_START_OFFSET; // = GPIO start offset within HW Param section.
452
453         /* Read the GPIO values for 32 GPIOs from EEPROM and map the function
454          * number to GPIO pin number to GPIO_Array
455          */
456         BeceemNVMRead(Adapter, (UINT *)ucGPIOInfo,dwReadValue,32);
457         for(ucIndex = 0; ucIndex < 32; ucIndex++)
458          {
459
460                  switch(ucGPIOInfo[ucIndex])
461                         {
462                                 case RED_LED:
463                                 {
464                                         GPIO_Array[RED_LED] = ucIndex;
465                                         Adapter->gpioBitMap |= (1<<ucIndex);
466                                         break;
467                                 }
468                                 case BLUE_LED:
469                                 {
470                                         GPIO_Array[BLUE_LED] = ucIndex;
471                                         Adapter->gpioBitMap |= (1<<ucIndex);
472                                         break;
473                                 }
474                                 case YELLOW_LED:
475                                 {
476                                          GPIO_Array[YELLOW_LED] = ucIndex;
477                                          Adapter->gpioBitMap |= (1<<ucIndex);
478                                          break;
479                                 }
480                                 case GREEN_LED:
481                                 {
482                                         GPIO_Array[GREEN_LED] = ucIndex;
483                                         Adapter->gpioBitMap |= (1<<ucIndex);
484                                         break;
485                                 }
486                                 default:
487                                         break;
488                         }
489
490                 }
491                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"GPIO's bit map correspond to LED :0x%X",Adapter->gpioBitMap);
492          return Status;
493 }
494
495
496 static int ReadConfigFileStructure(PMINI_ADAPTER Adapter, BOOLEAN *bEnableThread)
497 {
498         int Status = STATUS_SUCCESS;
499         UCHAR GPIO_Array[NUM_OF_LEDS+1]; /*Array to store GPIO numbers from EEPROM*/
500         UINT uiIndex = 0;
501         UINT uiNum_of_LED_Type = 0;
502         PUCHAR puCFGData        = NULL;
503         UCHAR bData = 0;
504         memset(GPIO_Array, DISABLE_GPIO_NUM, NUM_OF_LEDS+1);
505
506         if(!Adapter->pstargetparams || IS_ERR(Adapter->pstargetparams))
507         {
508                 BCM_DEBUG_PRINT (Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL, "Target Params not Avail.\n");
509                 return -ENOENT;
510         }
511
512         /*Populate GPIO_Array with GPIO numbers for LED functions*/
513         /*Read the GPIO numbers from EEPROM*/
514         Status = ReadLEDInformationFromEEPROM(Adapter, GPIO_Array);
515         if(Status == STATUS_IMAGE_CHECKSUM_MISMATCH)
516         {
517                 *bEnableThread = FALSE;
518                 return STATUS_SUCCESS;
519         }
520         else if(Status)
521         {
522                 *bEnableThread = FALSE;
523                 return Status;
524         }
525   /*
526      * CONFIG file read successfully. Deallocate the memory of
527      * uiFileNameBufferSize
528      */
529         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: Config file read successfully\n");
530         puCFGData = (PUCHAR) &Adapter->pstargetparams->HostDrvrConfig1;
531
532         /*
533          * Offset for HostDrvConfig1, HostDrvConfig2, HostDrvConfig3 which
534          * will have the information of LED type, LED on state for different
535          * driver state and LED blink state.
536          */
537
538         for(uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++)
539         {
540                 bData = *puCFGData;
541
542                 /*Check Bit 8 for polarity. If it is set, polarity is reverse polarity*/
543                 if(bData & 0x80)
544                 {
545                         Adapter->LEDInfo.LEDState[uiIndex].BitPolarity = 0;
546                         /*unset the bit 8*/
547                         bData = bData & 0x7f;
548                 }
549
550                 Adapter->LEDInfo.LEDState[uiIndex].LED_Type = bData;
551                 if(bData <= NUM_OF_LEDS)
552                         Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num = GPIO_Array[bData];
553                 else
554                         Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num = DISABLE_GPIO_NUM;
555
556                 puCFGData++;
557                 bData = *puCFGData;
558                 Adapter->LEDInfo.LEDState[uiIndex].LED_On_State = bData;
559                 puCFGData++;
560                 bData = *puCFGData;
561                 Adapter->LEDInfo.LEDState[uiIndex].LED_Blink_State= bData;
562                 puCFGData++;
563         }
564
565         /*Check if all the LED settings are disabled. If it is disabled, dont launch the LED control thread.*/
566         for(uiIndex = 0; uiIndex<NUM_OF_LEDS; uiIndex++)
567         {
568                 if((Adapter->LEDInfo.LEDState[uiIndex].LED_Type == DISABLE_GPIO_NUM) ||
569                         (Adapter->LEDInfo.LEDState[uiIndex].LED_Type == 0x7f) ||
570                         (Adapter->LEDInfo.LEDState[uiIndex].LED_Type == 0))
571                         uiNum_of_LED_Type++;
572         }
573         if(uiNum_of_LED_Type >= NUM_OF_LEDS)
574                 *bEnableThread = FALSE;
575
576 #if 0
577         for(uiIndex=0; uiIndex<NUM_OF_LEDS; uiIndex++)
578         {
579                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LEDState[%d].LED_Type = %x\n", uiIndex,
580                         Adapter->LEDInfo.LEDState[uiIndex].LED_Type);
581                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LEDState[%d].LED_On_State = %x\n", uiIndex,
582                         Adapter->LEDInfo.LEDState[uiIndex].LED_On_State);
583                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LEDState[%d].LED_Blink_State = %x\n", uiIndex,
584                         Adapter->LEDInfo.LEDState[uiIndex].LED_Blink_State);
585                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LEDState[%d].GPIO_Num = %x\n", uiIndex,
586                         Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num);
587         }
588         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: Polarity = %d\n",
589                         Adapter->LEDInfo.BitPolarty);
590 #endif
591         return Status;
592 }
593 //--------------------------------------------------------------------------
594 // Procedure:   LedGpioInit
595 //
596 // Description: Initializes LED GPIOs. Makes the LED GPIOs to OUTPUT mode and make the
597 //                        initial state to be OFF.
598 //
599 // Arguments:
600 //      Adapter - Pointer to MINI_ADAPTER structure.
601 //
602 // Returns: VOID
603 //
604 //-----------------------------------------------------------------------------
605
606 static VOID LedGpioInit(PMINI_ADAPTER Adapter)
607 {
608         UINT uiResetValue = 0;
609         UINT uiIndex      = 0;
610
611         /* Set all LED GPIO Mode to output mode */
612         if(rdmalt(Adapter, GPIO_MODE_REGISTER, &uiResetValue, sizeof(uiResetValue)) <0)
613                 BCM_DEBUG_PRINT (Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: RDM Failed\n");
614         for(uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++)
615         {
616                 if(Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num != DISABLE_GPIO_NUM)
617                         uiResetValue |= (1 << Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num);
618                 TURN_OFF_LED(1<<Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num,uiIndex);
619         }
620         if(wrmalt(Adapter, GPIO_MODE_REGISTER, &uiResetValue, sizeof(uiResetValue)) < 0)
621                 BCM_DEBUG_PRINT (Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: WRM Failed\n");
622
623         Adapter->LEDInfo.bIdle_led_off =  FALSE;
624 }
625 //-----------------------------------------------------------------------------
626
627 static INT BcmGetGPIOPinInfo(PMINI_ADAPTER Adapter, UCHAR *GPIO_num_tx, UCHAR *GPIO_num_rx ,UCHAR *uiLedTxIndex, UCHAR *uiLedRxIndex,LedEventInfo_t currdriverstate)
628 {
629         UINT uiIndex = 0;
630
631         *GPIO_num_tx = DISABLE_GPIO_NUM;
632         *GPIO_num_rx = DISABLE_GPIO_NUM;
633
634         for(uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++)
635         {
636
637                 if((currdriverstate == NORMAL_OPERATION)||
638                         (currdriverstate == IDLEMODE_EXIT)||
639                         (currdriverstate == FW_DOWNLOAD))
640                 {
641                         if(Adapter->LEDInfo.LEDState[uiIndex].LED_Blink_State & currdriverstate)
642                         {
643                                 if(Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num != DISABLE_GPIO_NUM)
644                                 {
645                                         if(*GPIO_num_tx == DISABLE_GPIO_NUM)
646                                         {
647                                                 *GPIO_num_tx = Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num;
648                                                 *uiLedTxIndex = uiIndex;
649                                         }
650                                         else
651                                         {
652                                                 *GPIO_num_rx = Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num;
653                                                 *uiLedRxIndex = uiIndex;
654                                         }
655                                 }
656                         }
657                 }
658                 else
659                 {
660                         if(Adapter->LEDInfo.LEDState[uiIndex].LED_On_State & currdriverstate)
661                         {
662                                 if(Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num != DISABLE_GPIO_NUM)
663                                 {
664                                         *GPIO_num_tx = Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num;
665                                         *uiLedTxIndex = uiIndex;
666                                 }
667                         }
668                 }
669         }
670         return STATUS_SUCCESS ;
671 }
672 static VOID LEDControlThread(PMINI_ADAPTER Adapter)
673 {
674         UINT uiIndex = 0;
675         UCHAR GPIO_num = 0;
676         UCHAR uiLedIndex = 0 ;
677         UINT uiResetValue = 0;
678         LedEventInfo_t currdriverstate = 0;
679         ulong timeout = 0;
680
681         INT Status = 0;
682
683         UCHAR  dummyGPIONum = 0;
684         UCHAR  dummyIndex = 0;
685
686         //currdriverstate = Adapter->DriverState;
687         Adapter->LEDInfo.bIdleMode_tx_from_host = FALSE;
688
689         /*Wait till event is triggered*/
690         //wait_event(Adapter->LEDInfo.notify_led_event,
691                         //      currdriverstate!= Adapter->DriverState);
692
693         GPIO_num = DISABLE_GPIO_NUM ;
694
695         while(TRUE)
696         {
697                 /*Wait till event is triggered*/
698                 if( (GPIO_num == DISABLE_GPIO_NUM)
699                                                 ||
700                         ((currdriverstate != FW_DOWNLOAD) &&
701                          (currdriverstate != NORMAL_OPERATION) &&
702                          (currdriverstate != LOWPOWER_MODE_ENTER))
703                                                 ||
704                          (currdriverstate == LED_THREAD_INACTIVE)       )
705                 {
706                         Status = wait_event_interruptible(Adapter->LEDInfo.notify_led_event,
707                                 currdriverstate != Adapter->DriverState || kthread_should_stop());
708                 }
709
710                 if(kthread_should_stop() || Adapter->device_removed )
711                 {
712                         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL, "Led thread got signal to exit..hence exiting");
713                         Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_DISABLED;
714                         TURN_OFF_LED(1<<GPIO_num, uiLedIndex);
715                         return ;//STATUS_FAILURE;
716                 }
717         #if 0
718                 if(Adapter->device_removed)
719                 {
720                         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"Device removed hence exiting from Led Thread..");
721                         return ; //-ENODEV;
722                 }
723         #endif
724                 #if 0
725                 if((GPIO_num != DISABLE_GPIO_NUM) &&
726                         ((currdriverstate != FW_DOWNLOAD) &&
727                         (currdriverstate != NORMAL_OPERATION) &&
728                         (currdriverstate != IDLEMODE_EXIT)))
729                         TURN_OFF_LED(1<<GPIO_num, uiLedIndex);
730                 #endif
731
732                 if(GPIO_num != DISABLE_GPIO_NUM)
733                 {
734                         TURN_OFF_LED(1<<GPIO_num, uiLedIndex);
735                 }
736
737                 if(Adapter->LEDInfo.bLedInitDone == FALSE)
738                 {
739                         LedGpioInit(Adapter);
740                         Adapter->LEDInfo.bLedInitDone = TRUE;
741                 }
742
743                 switch(Adapter->DriverState)
744                 {
745                         case DRIVER_INIT:
746                         {
747                                 currdriverstate = DRIVER_INIT;//Adapter->DriverState;
748         #if 0
749                                 LedGpioInit(Adapter);
750                                 Adapter->LEDInfo.bLedInitDone = TRUE;
751         #endif
752                                 BcmGetGPIOPinInfo(Adapter, &GPIO_num, &dummyGPIONum, &uiLedIndex, &dummyIndex, currdriverstate);
753
754                                 if(GPIO_num  != DISABLE_GPIO_NUM)
755                                 {
756                                         TURN_ON_LED(1<<GPIO_num, uiLedIndex);
757                                 }
758                         }
759                         break;
760                         case FW_DOWNLOAD:
761                         {
762                                 //BCM_DEBUG_PRINT (Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: FW_DN_DONE called\n");
763                                 currdriverstate = FW_DOWNLOAD;
764                         #if 0
765                                 if(Adapter->LEDInfo.bLedInitDone == FALSE)
766                                 {
767                                         LedGpioInit(Adapter);
768                                         Adapter->LEDInfo.bLedInitDone = TRUE;
769                                 }
770                         #endif
771                                 BcmGetGPIOPinInfo(Adapter, &GPIO_num, &dummyGPIONum,  &uiLedIndex, &dummyIndex, currdriverstate);
772
773                                 if(GPIO_num != DISABLE_GPIO_NUM)
774                                 {
775                                         timeout = 50;
776                                         LED_Blink(Adapter, 1<<GPIO_num, uiLedIndex, timeout, -1,currdriverstate);
777                                 }
778                         }
779                         break;
780                         case FW_DOWNLOAD_DONE:
781                         {
782                                 currdriverstate = FW_DOWNLOAD_DONE;
783                                 BcmGetGPIOPinInfo(Adapter, &GPIO_num, &dummyGPIONum, &uiLedIndex, &dummyIndex,currdriverstate);
784                                 if(GPIO_num != DISABLE_GPIO_NUM)
785                                 {
786                                         TURN_ON_LED(1<<GPIO_num, uiLedIndex);
787                                 }
788                         }
789                         break;
790
791                         case SHUTDOWN_EXIT:
792                         #if 0
793                         if(Adapter->ulPowerSaveMode == DEVICE_POWERSAVE_MODE_AS_PMU_SHUTDOWN)
794                         {
795                                 LedGpioInit(Adapter);
796                         }
797                         #endif
798                         //no break, continue to NO_NETWORK_ENTRY state as well.
799
800                         case NO_NETWORK_ENTRY:
801                         {
802                                 currdriverstate = NO_NETWORK_ENTRY;
803                                 BcmGetGPIOPinInfo(Adapter, &GPIO_num, &dummyGPIONum, &uiLedIndex,&dummyGPIONum,currdriverstate);
804                                 if(GPIO_num != DISABLE_GPIO_NUM)
805                                 {
806                                         TURN_ON_LED(1<<GPIO_num, uiLedIndex);
807                                 }
808                         }
809                         break;
810                         case NORMAL_OPERATION:
811                         {
812                                 UCHAR GPIO_num_tx = DISABLE_GPIO_NUM;
813                                 UCHAR GPIO_num_rx = DISABLE_GPIO_NUM;
814                                 UCHAR uiLEDTx = 0;
815                                 UCHAR uiLEDRx = 0;
816                                 currdriverstate = NORMAL_OPERATION;
817                                 Adapter->LEDInfo.bIdle_led_off =  FALSE;
818
819                                 BcmGetGPIOPinInfo(Adapter, &GPIO_num_tx, &GPIO_num_rx, &uiLEDTx,&uiLEDRx,currdriverstate);
820                                 if((GPIO_num_tx == DISABLE_GPIO_NUM) && (GPIO_num_rx == DISABLE_GPIO_NUM))
821                                 {
822                                         GPIO_num = DISABLE_GPIO_NUM ;
823                                 }
824                                 else
825                                 {
826                                         /*If single LED is selected, use same for both Tx and Rx*/
827                                         if(GPIO_num_tx == DISABLE_GPIO_NUM)
828                                         {
829                                                 GPIO_num_tx = GPIO_num_rx;
830                                                 uiLEDTx = uiLEDRx;
831                                         }
832                                         else if(GPIO_num_rx == DISABLE_GPIO_NUM)
833                                         {
834                                                 GPIO_num_rx = GPIO_num_tx;
835                                                 uiLEDRx = uiLEDTx;
836                                         }
837                                 /*Blink the LED in proportionate to Tx and Rx transmissions.*/
838                                         LED_Proportional_Blink(Adapter, GPIO_num_tx, uiLEDTx, GPIO_num_rx, uiLEDRx,currdriverstate);
839                                 }
840                         }
841                         break;
842                         case LOWPOWER_MODE_ENTER:
843                         {
844                                 currdriverstate  = LOWPOWER_MODE_ENTER;
845                                 if( DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING == Adapter->ulPowerSaveMode)
846                                 {
847                                         /* Turn OFF all the LED */
848                                         uiResetValue = 0;
849                                         for(uiIndex =0; uiIndex < NUM_OF_LEDS; uiIndex++)
850                                         {
851                                                 if(Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num != DISABLE_GPIO_NUM)
852                                                 TURN_OFF_LED((1<<Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num),uiIndex);
853                                         }
854
855                                 }
856                                 /* Turn off LED And WAKE-UP for Sendinf IDLE mode ACK */
857                                 Adapter->LEDInfo.bLedInitDone = FALSE;
858                                 Adapter->LEDInfo.bIdle_led_off =  TRUE;
859                                 wake_up(&Adapter->LEDInfo.idleModeSyncEvent);
860                                 GPIO_num = DISABLE_GPIO_NUM;
861                                 break;
862                         }
863                         case IDLEMODE_CONTINUE:
864                         {
865                                 currdriverstate = IDLEMODE_CONTINUE;
866                                 GPIO_num = DISABLE_GPIO_NUM;
867                         }
868                         break;
869                         case IDLEMODE_EXIT:
870                         {
871 #if 0
872                                 UCHAR GPIO_num_tx = DISABLE_GPIO_NUM;
873                                 UCHAR GPIO_num_rx = DISABLE_GPIO_NUM;
874                                 UCHAR uiTxLedIndex = 0;
875                                 UCHAR uiRxLedIndex = 0;
876
877                                 currdriverstate  = IDLEMODE_EXIT;
878                                 if(DEVICE_POWERSAVE_MODE_AS_PMU_SHUTDOWN == Adapter->ulPowerSaveMode)
879                                 {
880                                         LedGpioInit(Adapter);
881                                 }
882                                 BcmGetGPIOPinInfo(Adapter, &GPIO_num_tx, &GPIO_num_rx, &uiTxLedIndex,&uiRxLedIndex,currdriverstate);
883
884                                 Adapter->LEDInfo.bIdle_led_off =  FALSE;
885
886                                 if((GPIO_num_tx == DISABLE_GPIO_NUM) && (GPIO_num_rx == DISABLE_GPIO_NUM))
887                                 {
888                                         GPIO_num = DISABLE_GPIO_NUM ;
889                                 }
890                                 else
891                                 {
892                                         timeout = 50;
893                                         if(Adapter->LEDInfo.bIdleMode_tx_from_host)
894                                                 LED_Blink(Adapter, 1<<GPIO_num_tx, uiTxLedIndex, timeout, -1,currdriverstate);
895                                         else
896                                                 LED_Blink(Adapter, 1<<GPIO_num_rx, uiRxLedIndex, timeout, -1,currdriverstate);
897                                 }
898 #endif
899                         }
900                         break;
901                         case DRIVER_HALT:
902                         {
903                                 currdriverstate = DRIVER_HALT;
904                                 GPIO_num = DISABLE_GPIO_NUM;
905                                 for(uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++)
906                                 {
907                                         if(Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num !=
908                                                 DISABLE_GPIO_NUM)
909                                                 TURN_OFF_LED((1<<Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num),uiIndex);
910                                 }
911                                 //Adapter->DriverState = DRIVER_INIT;
912                         }
913                         break;
914                         case LED_THREAD_INACTIVE :
915                         {
916                                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"InActivating LED thread...");
917                                 currdriverstate = LED_THREAD_INACTIVE;
918                                 Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_RUNNING_INACTIVELY ;
919                                 Adapter->LEDInfo.bLedInitDone = FALSE ;
920                                 //disable ALL LED
921                                 for(uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++)
922                                 {
923                                         if(Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num !=
924                                                 DISABLE_GPIO_NUM)
925                                                 TURN_OFF_LED((1<<Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num),uiIndex);
926                                 }
927                         }
928                         break;
929                         case LED_THREAD_ACTIVE :
930                         {
931                                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"Activating LED thread again...");
932                                 if(Adapter->LinkUpStatus == FALSE)
933                                         Adapter->DriverState = NO_NETWORK_ENTRY;
934                                 else
935                                         Adapter->DriverState = NORMAL_OPERATION;
936
937                                 Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_RUNNING_ACTIVELY ;
938                         }
939                         break;
940                         //return;
941                         default:
942                                 break;
943                 }
944         }
945         Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_DISABLED;
946 }
947
948 int InitLedSettings(PMINI_ADAPTER Adapter)
949 {
950         int Status = STATUS_SUCCESS;
951         BOOLEAN bEnableThread = TRUE;
952         UCHAR uiIndex = 0;
953
954         /*Initially set BitPolarity to normal polarity. The bit 8 of LED type
955  *        is used to change the polarity of the LED.*/
956
957         for(uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) {
958                 Adapter->LEDInfo.LEDState[uiIndex].BitPolarity = 1;
959         }
960
961         /*Read the LED settings of CONFIG file and map it to GPIO numbers in EEPROM*/
962         Status = ReadConfigFileStructure(Adapter, &bEnableThread);
963         if(STATUS_SUCCESS != Status)
964         {
965                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: FAILED in ReadConfigFileStructure\n");
966                 return Status;
967         }
968
969         if(Adapter->LEDInfo.led_thread_running)
970         {
971                 if(bEnableThread)
972                         ;
973                 else
974                 {
975                         Adapter->DriverState = DRIVER_HALT;
976                         wake_up(&Adapter->LEDInfo.notify_led_event);
977                         Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_DISABLED;
978                 }
979
980         }
981
982         else if(bEnableThread)
983         {
984                 /*Create secondary thread to handle the LEDs*/
985                 init_waitqueue_head(&Adapter->LEDInfo.notify_led_event);
986                 init_waitqueue_head(&Adapter->LEDInfo.idleModeSyncEvent);
987                 Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_RUNNING_ACTIVELY;
988                 Adapter->LEDInfo.bIdle_led_off =  FALSE;
989                 Adapter->LEDInfo.led_cntrl_threadid = kthread_run((int (*)(void *))
990             LEDControlThread, Adapter, "led_control_thread");
991                 if(IS_ERR(Adapter->LEDInfo.led_cntrl_threadid))
992         {
993                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL, "Not able to spawn Kernel Thread\n");
994                         Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_DISABLED;
995                 return PTR_ERR(Adapter->LEDInfo.led_cntrl_threadid);
996         }
997         }
998         return Status;
999 }