97adaae7dfc0c4fef031a24854c9223ad3bf0610
[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 #ifndef BCM_SHM_INTERFACE
501         UINT uiIndex = 0;
502         UINT uiNum_of_LED_Type = 0;
503         PUCHAR puCFGData        = NULL;
504         UCHAR bData = 0;
505 #endif
506         memset(GPIO_Array, DISABLE_GPIO_NUM, NUM_OF_LEDS+1);
507
508         if(!Adapter->pstargetparams || IS_ERR(Adapter->pstargetparams))
509         {
510                 BCM_DEBUG_PRINT (Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL, "Target Params not Avail.\n");
511                 return -ENOENT;
512         }
513
514         /*Populate GPIO_Array with GPIO numbers for LED functions*/
515         /*Read the GPIO numbers from EEPROM*/
516         Status = ReadLEDInformationFromEEPROM(Adapter, GPIO_Array);
517         if(Status == STATUS_IMAGE_CHECKSUM_MISMATCH)
518         {
519                 *bEnableThread = FALSE;
520                 return STATUS_SUCCESS;
521         }
522         else if(Status)
523         {
524                 *bEnableThread = FALSE;
525                 return Status;
526         }
527 #ifdef BCM_SHM_INTERFACE
528         *bEnableThread = FALSE;
529         return Status ;
530 #else
531   /*
532      * CONFIG file read successfully. Deallocate the memory of
533      * uiFileNameBufferSize
534      */
535         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: Config file read successfully\n");
536         puCFGData = (PUCHAR) &Adapter->pstargetparams->HostDrvrConfig1;
537
538         /*
539          * Offset for HostDrvConfig1, HostDrvConfig2, HostDrvConfig3 which
540          * will have the information of LED type, LED on state for different
541          * driver state and LED blink state.
542          */
543
544         for(uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++)
545         {
546                 bData = *puCFGData;
547
548                 /*Check Bit 8 for polarity. If it is set, polarity is reverse polarity*/
549                 if(bData & 0x80)
550                 {
551                         Adapter->LEDInfo.LEDState[uiIndex].BitPolarity = 0;
552                         /*unset the bit 8*/
553                         bData = bData & 0x7f;
554                 }
555
556                 Adapter->LEDInfo.LEDState[uiIndex].LED_Type = bData;
557                 if(bData <= NUM_OF_LEDS)
558                         Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num = GPIO_Array[bData];
559                 else
560                         Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num = DISABLE_GPIO_NUM;
561
562                 puCFGData++;
563                 bData = *puCFGData;
564                 Adapter->LEDInfo.LEDState[uiIndex].LED_On_State = bData;
565                 puCFGData++;
566                 bData = *puCFGData;
567                 Adapter->LEDInfo.LEDState[uiIndex].LED_Blink_State= bData;
568                 puCFGData++;
569         }
570
571         /*Check if all the LED settings are disabled. If it is disabled, dont launch the LED control thread.*/
572         for(uiIndex = 0; uiIndex<NUM_OF_LEDS; uiIndex++)
573         {
574                 if((Adapter->LEDInfo.LEDState[uiIndex].LED_Type == DISABLE_GPIO_NUM) ||
575                         (Adapter->LEDInfo.LEDState[uiIndex].LED_Type == 0x7f) ||
576                         (Adapter->LEDInfo.LEDState[uiIndex].LED_Type == 0))
577                         uiNum_of_LED_Type++;
578         }
579         if(uiNum_of_LED_Type >= NUM_OF_LEDS)
580                 *bEnableThread = FALSE;
581 #endif
582
583 #if 0
584         for(uiIndex=0; uiIndex<NUM_OF_LEDS; uiIndex++)
585         {
586                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LEDState[%d].LED_Type = %x\n", uiIndex,
587                         Adapter->LEDInfo.LEDState[uiIndex].LED_Type);
588                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LEDState[%d].LED_On_State = %x\n", uiIndex,
589                         Adapter->LEDInfo.LEDState[uiIndex].LED_On_State);
590                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LEDState[%d].LED_Blink_State = %x\n", uiIndex,
591                         Adapter->LEDInfo.LEDState[uiIndex].LED_Blink_State);
592                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LEDState[%d].GPIO_Num = %x\n", uiIndex,
593                         Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num);
594         }
595         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: Polarity = %d\n",
596                         Adapter->LEDInfo.BitPolarty);
597 #endif
598         return Status;
599 }
600 //--------------------------------------------------------------------------
601 // Procedure:   LedGpioInit
602 //
603 // Description: Initializes LED GPIOs. Makes the LED GPIOs to OUTPUT mode and make the
604 //                        initial state to be OFF.
605 //
606 // Arguments:
607 //      Adapter - Pointer to MINI_ADAPTER structure.
608 //
609 // Returns: VOID
610 //
611 //-----------------------------------------------------------------------------
612
613 static VOID LedGpioInit(PMINI_ADAPTER Adapter)
614 {
615         UINT uiResetValue = 0;
616         UINT uiIndex      = 0;
617
618         /* Set all LED GPIO Mode to output mode */
619         if(rdmalt(Adapter, GPIO_MODE_REGISTER, &uiResetValue, sizeof(uiResetValue)) <0)
620                 BCM_DEBUG_PRINT (Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: RDM Failed\n");
621         for(uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++)
622         {
623                 if(Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num != DISABLE_GPIO_NUM)
624                         uiResetValue |= (1 << Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num);
625                 TURN_OFF_LED(1<<Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num,uiIndex);
626         }
627         if(wrmalt(Adapter, GPIO_MODE_REGISTER, &uiResetValue, sizeof(uiResetValue)) < 0)
628                 BCM_DEBUG_PRINT (Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: WRM Failed\n");
629
630         Adapter->LEDInfo.bIdle_led_off =  FALSE;
631 }
632 //-----------------------------------------------------------------------------
633
634 static INT BcmGetGPIOPinInfo(PMINI_ADAPTER Adapter, UCHAR *GPIO_num_tx, UCHAR *GPIO_num_rx ,UCHAR *uiLedTxIndex, UCHAR *uiLedRxIndex,LedEventInfo_t currdriverstate)
635 {
636         UINT uiIndex = 0;
637
638         *GPIO_num_tx = DISABLE_GPIO_NUM;
639         *GPIO_num_rx = DISABLE_GPIO_NUM;
640
641         for(uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++)
642         {
643
644                 if((currdriverstate == NORMAL_OPERATION)||
645                         (currdriverstate == IDLEMODE_EXIT)||
646                         (currdriverstate == FW_DOWNLOAD))
647                 {
648                         if(Adapter->LEDInfo.LEDState[uiIndex].LED_Blink_State & currdriverstate)
649                         {
650                                 if(Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num != DISABLE_GPIO_NUM)
651                                 {
652                                         if(*GPIO_num_tx == DISABLE_GPIO_NUM)
653                                         {
654                                                 *GPIO_num_tx = Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num;
655                                                 *uiLedTxIndex = uiIndex;
656                                         }
657                                         else
658                                         {
659                                                 *GPIO_num_rx = Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num;
660                                                 *uiLedRxIndex = uiIndex;
661                                         }
662                                 }
663                         }
664                 }
665                 else
666                 {
667                         if(Adapter->LEDInfo.LEDState[uiIndex].LED_On_State & currdriverstate)
668                         {
669                                 if(Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num != DISABLE_GPIO_NUM)
670                                 {
671                                         *GPIO_num_tx = Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num;
672                                         *uiLedTxIndex = uiIndex;
673                                 }
674                         }
675                 }
676         }
677         return STATUS_SUCCESS ;
678 }
679 static VOID LEDControlThread(PMINI_ADAPTER Adapter)
680 {
681         UINT uiIndex = 0;
682         UCHAR GPIO_num = 0;
683         UCHAR uiLedIndex = 0 ;
684         UINT uiResetValue = 0;
685         LedEventInfo_t currdriverstate = 0;
686         ulong timeout = 0;
687
688         INT Status = 0;
689
690         UCHAR  dummyGPIONum = 0;
691         UCHAR  dummyIndex = 0;
692
693         //currdriverstate = Adapter->DriverState;
694         Adapter->LEDInfo.bIdleMode_tx_from_host = FALSE;
695
696         /*Wait till event is triggered*/
697         //wait_event(Adapter->LEDInfo.notify_led_event,
698                         //      currdriverstate!= Adapter->DriverState);
699
700         GPIO_num = DISABLE_GPIO_NUM ;
701
702         while(TRUE)
703         {
704                 /*Wait till event is triggered*/
705                 if( (GPIO_num == DISABLE_GPIO_NUM)
706                                                 ||
707                         ((currdriverstate != FW_DOWNLOAD) &&
708                          (currdriverstate != NORMAL_OPERATION) &&
709                          (currdriverstate != LOWPOWER_MODE_ENTER))
710                                                 ||
711                          (currdriverstate == LED_THREAD_INACTIVE)       )
712                 {
713                         Status = wait_event_interruptible(Adapter->LEDInfo.notify_led_event,
714                                 currdriverstate != Adapter->DriverState || kthread_should_stop());
715                 }
716
717                 if(kthread_should_stop() || Adapter->device_removed )
718                 {
719                         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL, "Led thread got signal to exit..hence exiting");
720                         Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_DISABLED;
721                         TURN_OFF_LED(1<<GPIO_num, uiLedIndex);
722                         return ;//STATUS_FAILURE;
723                 }
724         #if 0
725                 if(Adapter->device_removed)
726                 {
727                         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"Device removed hence exiting from Led Thread..");
728                         return ; //-ENODEV;
729                 }
730         #endif
731                 #if 0
732                 if((GPIO_num != DISABLE_GPIO_NUM) &&
733                         ((currdriverstate != FW_DOWNLOAD) &&
734                         (currdriverstate != NORMAL_OPERATION) &&
735                         (currdriverstate != IDLEMODE_EXIT)))
736                         TURN_OFF_LED(1<<GPIO_num, uiLedIndex);
737                 #endif
738
739                 if(GPIO_num != DISABLE_GPIO_NUM)
740                 {
741                         TURN_OFF_LED(1<<GPIO_num, uiLedIndex);
742                 }
743
744                 if(Adapter->LEDInfo.bLedInitDone == FALSE)
745                 {
746                         LedGpioInit(Adapter);
747                         Adapter->LEDInfo.bLedInitDone = TRUE;
748                 }
749
750                 switch(Adapter->DriverState)
751                 {
752                         case DRIVER_INIT:
753                         {
754                                 currdriverstate = DRIVER_INIT;//Adapter->DriverState;
755         #if 0
756                                 LedGpioInit(Adapter);
757                                 Adapter->LEDInfo.bLedInitDone = TRUE;
758         #endif
759                                 BcmGetGPIOPinInfo(Adapter, &GPIO_num, &dummyGPIONum, &uiLedIndex, &dummyIndex, currdriverstate);
760
761                                 if(GPIO_num  != DISABLE_GPIO_NUM)
762                                 {
763                                         TURN_ON_LED(1<<GPIO_num, uiLedIndex);
764                                 }
765                         }
766                         break;
767                         case FW_DOWNLOAD:
768                         {
769                                 //BCM_DEBUG_PRINT (Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: FW_DN_DONE called\n");
770                                 currdriverstate = FW_DOWNLOAD;
771                         #if 0
772                                 if(Adapter->LEDInfo.bLedInitDone == FALSE)
773                                 {
774                                         LedGpioInit(Adapter);
775                                         Adapter->LEDInfo.bLedInitDone = TRUE;
776                                 }
777                         #endif
778                                 BcmGetGPIOPinInfo(Adapter, &GPIO_num, &dummyGPIONum,  &uiLedIndex, &dummyIndex, currdriverstate);
779
780                                 if(GPIO_num != DISABLE_GPIO_NUM)
781                                 {
782                                         timeout = 50;
783                                         LED_Blink(Adapter, 1<<GPIO_num, uiLedIndex, timeout, -1,currdriverstate);
784                                 }
785                         }
786                         break;
787                         case FW_DOWNLOAD_DONE:
788                         {
789                                 currdriverstate = FW_DOWNLOAD_DONE;
790                                 BcmGetGPIOPinInfo(Adapter, &GPIO_num, &dummyGPIONum, &uiLedIndex, &dummyIndex,currdriverstate);
791                                 if(GPIO_num != DISABLE_GPIO_NUM)
792                                 {
793                                         TURN_ON_LED(1<<GPIO_num, uiLedIndex);
794                                 }
795                         }
796                         break;
797
798                         case SHUTDOWN_EXIT:
799                         #if 0
800                         if(Adapter->ulPowerSaveMode == DEVICE_POWERSAVE_MODE_AS_PMU_SHUTDOWN)
801                         {
802                                 LedGpioInit(Adapter);
803                         }
804                         #endif
805                         //no break, continue to NO_NETWORK_ENTRY state as well.
806
807                         case NO_NETWORK_ENTRY:
808                         {
809                                 currdriverstate = NO_NETWORK_ENTRY;
810                                 BcmGetGPIOPinInfo(Adapter, &GPIO_num, &dummyGPIONum, &uiLedIndex,&dummyGPIONum,currdriverstate);
811                                 if(GPIO_num != DISABLE_GPIO_NUM)
812                                 {
813                                         TURN_ON_LED(1<<GPIO_num, uiLedIndex);
814                                 }
815                         }
816                         break;
817                         case NORMAL_OPERATION:
818                         {
819                                 UCHAR GPIO_num_tx = DISABLE_GPIO_NUM;
820                                 UCHAR GPIO_num_rx = DISABLE_GPIO_NUM;
821                                 UCHAR uiLEDTx = 0;
822                                 UCHAR uiLEDRx = 0;
823                                 currdriverstate = NORMAL_OPERATION;
824                                 Adapter->LEDInfo.bIdle_led_off =  FALSE;
825
826                                 BcmGetGPIOPinInfo(Adapter, &GPIO_num_tx, &GPIO_num_rx, &uiLEDTx,&uiLEDRx,currdriverstate);
827                                 if((GPIO_num_tx == DISABLE_GPIO_NUM) && (GPIO_num_rx == DISABLE_GPIO_NUM))
828                                 {
829                                         GPIO_num = DISABLE_GPIO_NUM ;
830                                 }
831                                 else
832                                 {
833                                         /*If single LED is selected, use same for both Tx and Rx*/
834                                         if(GPIO_num_tx == DISABLE_GPIO_NUM)
835                                         {
836                                                 GPIO_num_tx = GPIO_num_rx;
837                                                 uiLEDTx = uiLEDRx;
838                                         }
839                                         else if(GPIO_num_rx == DISABLE_GPIO_NUM)
840                                         {
841                                                 GPIO_num_rx = GPIO_num_tx;
842                                                 uiLEDRx = uiLEDTx;
843                                         }
844                                 /*Blink the LED in proportionate to Tx and Rx transmissions.*/
845                                         LED_Proportional_Blink(Adapter, GPIO_num_tx, uiLEDTx, GPIO_num_rx, uiLEDRx,currdriverstate);
846                                 }
847                         }
848                         break;
849                         case LOWPOWER_MODE_ENTER:
850                         {
851                                 currdriverstate  = LOWPOWER_MODE_ENTER;
852                                 if( DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING == Adapter->ulPowerSaveMode)
853                                 {
854                                         /* Turn OFF all the LED */
855                                         uiResetValue = 0;
856                                         for(uiIndex =0; uiIndex < NUM_OF_LEDS; uiIndex++)
857                                         {
858                                                 if(Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num != DISABLE_GPIO_NUM)
859                                                 TURN_OFF_LED((1<<Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num),uiIndex);
860                                         }
861
862                                 }
863                                 /* Turn off LED And WAKE-UP for Sendinf IDLE mode ACK */
864                                 Adapter->LEDInfo.bLedInitDone = FALSE;
865                                 Adapter->LEDInfo.bIdle_led_off =  TRUE;
866                                 wake_up(&Adapter->LEDInfo.idleModeSyncEvent);
867                                 GPIO_num = DISABLE_GPIO_NUM;
868                                 break;
869                         }
870                         case IDLEMODE_CONTINUE:
871                         {
872                                 currdriverstate = IDLEMODE_CONTINUE;
873                                 GPIO_num = DISABLE_GPIO_NUM;
874                         }
875                         break;
876                         case IDLEMODE_EXIT:
877                         {
878 #if 0
879                                 UCHAR GPIO_num_tx = DISABLE_GPIO_NUM;
880                                 UCHAR GPIO_num_rx = DISABLE_GPIO_NUM;
881                                 UCHAR uiTxLedIndex = 0;
882                                 UCHAR uiRxLedIndex = 0;
883
884                                 currdriverstate  = IDLEMODE_EXIT;
885                                 if(DEVICE_POWERSAVE_MODE_AS_PMU_SHUTDOWN == Adapter->ulPowerSaveMode)
886                                 {
887                                         LedGpioInit(Adapter);
888                                 }
889                                 BcmGetGPIOPinInfo(Adapter, &GPIO_num_tx, &GPIO_num_rx, &uiTxLedIndex,&uiRxLedIndex,currdriverstate);
890
891                                 Adapter->LEDInfo.bIdle_led_off =  FALSE;
892
893                                 if((GPIO_num_tx == DISABLE_GPIO_NUM) && (GPIO_num_rx == DISABLE_GPIO_NUM))
894                                 {
895                                         GPIO_num = DISABLE_GPIO_NUM ;
896                                 }
897                                 else
898                                 {
899                                         timeout = 50;
900                                         if(Adapter->LEDInfo.bIdleMode_tx_from_host)
901                                                 LED_Blink(Adapter, 1<<GPIO_num_tx, uiTxLedIndex, timeout, -1,currdriverstate);
902                                         else
903                                                 LED_Blink(Adapter, 1<<GPIO_num_rx, uiRxLedIndex, timeout, -1,currdriverstate);
904                                 }
905 #endif
906                         }
907                         break;
908                         case DRIVER_HALT:
909                         {
910                                 currdriverstate = DRIVER_HALT;
911                                 GPIO_num = DISABLE_GPIO_NUM;
912                                 for(uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++)
913                                 {
914                                         if(Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num !=
915                                                 DISABLE_GPIO_NUM)
916                                                 TURN_OFF_LED((1<<Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num),uiIndex);
917                                 }
918                                 //Adapter->DriverState = DRIVER_INIT;
919                         }
920                         break;
921                         case LED_THREAD_INACTIVE :
922                         {
923                                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"InActivating LED thread...");
924                                 currdriverstate = LED_THREAD_INACTIVE;
925                                 Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_RUNNING_INACTIVELY ;
926                                 Adapter->LEDInfo.bLedInitDone = FALSE ;
927                                 //disable ALL LED
928                                 for(uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++)
929                                 {
930                                         if(Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num !=
931                                                 DISABLE_GPIO_NUM)
932                                                 TURN_OFF_LED((1<<Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num),uiIndex);
933                                 }
934                         }
935                         break;
936                         case LED_THREAD_ACTIVE :
937                         {
938                                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"Activating LED thread again...");
939                                 if(Adapter->LinkUpStatus == FALSE)
940                                         Adapter->DriverState = NO_NETWORK_ENTRY;
941                                 else
942                                         Adapter->DriverState = NORMAL_OPERATION;
943
944                                 Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_RUNNING_ACTIVELY ;
945                         }
946                         break;
947                         //return;
948                         default:
949                                 break;
950                 }
951         }
952         Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_DISABLED;
953 }
954
955 int InitLedSettings(PMINI_ADAPTER Adapter)
956 {
957         int Status = STATUS_SUCCESS;
958         BOOLEAN bEnableThread = TRUE;
959         UCHAR uiIndex = 0;
960
961         /*Initially set BitPolarity to normal polarity. The bit 8 of LED type
962  *        is used to change the polarity of the LED.*/
963
964         for(uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) {
965                 Adapter->LEDInfo.LEDState[uiIndex].BitPolarity = 1;
966         }
967
968         /*Read the LED settings of CONFIG file and map it to GPIO numbers in EEPROM*/
969         Status = ReadConfigFileStructure(Adapter, &bEnableThread);
970         if(STATUS_SUCCESS != Status)
971         {
972                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: FAILED in ReadConfigFileStructure\n");
973                 return Status;
974         }
975
976         if(Adapter->LEDInfo.led_thread_running)
977         {
978                 if(bEnableThread)
979                         ;
980                 else
981                 {
982                         Adapter->DriverState = DRIVER_HALT;
983                         wake_up(&Adapter->LEDInfo.notify_led_event);
984                         Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_DISABLED;
985                 }
986
987         }
988
989         else if(bEnableThread)
990         {
991                 /*Create secondary thread to handle the LEDs*/
992                 init_waitqueue_head(&Adapter->LEDInfo.notify_led_event);
993                 init_waitqueue_head(&Adapter->LEDInfo.idleModeSyncEvent);
994                 Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_RUNNING_ACTIVELY;
995                 Adapter->LEDInfo.bIdle_led_off =  FALSE;
996                 Adapter->LEDInfo.led_cntrl_threadid = kthread_run((int (*)(void *))
997             LEDControlThread, Adapter, "led_control_thread");
998                 if(IS_ERR(Adapter->LEDInfo.led_cntrl_threadid))
999         {
1000                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL, "Not able to spawn Kernel Thread\n");
1001                         Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_DISABLED;
1002                 return PTR_ERR(Adapter->LEDInfo.led_cntrl_threadid);
1003         }
1004         }
1005         return Status;
1006 }