http://downloads.netgear.com/files/GPL/GPL_Source_V361j_DM111PSP_series_consumer_rele...
[bcm963xx.git] / bcmdrivers / opensource / char / board / bcm963xx / impl1 / bcm63xx_led.c
1 /*
2 <:copyright-gpl 
3  Copyright 2002 Broadcom Corp. All Rights Reserved. 
4  
5  This program is free software; you can distribute it and/or modify it 
6  under the terms of the GNU General Public License (Version 2) as 
7  published by the Free Software Foundation. 
8  
9  This program is distributed in the hope it will be useful, but WITHOUT 
10  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
11  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License 
12  for more details. 
13  
14  You should have received a copy of the GNU General Public License along 
15  with this program; if not, write to the Free Software Foundation, Inc., 
16  59 Temple Place - Suite 330, Boston MA 02111-1307, USA. 
17 :>
18 */
19 /***************************************************************************
20  * File Name  : bcm63xx_led.c
21  *
22  * Description: 
23  *
24  *    This file contains bcm963xx board led control API functions. 
25  *
26  *    To use it, do the following
27  *
28  *    1). define in the board.c the following led mappping
29  *        const LED_MAP_PAIR cLedMapping45GW[] =
30  *        {   // led name     Initial state       physical pin (ledMask)
31  *            {kLedUsb,       kLedStateOff,       GPIO_LED_PIN_7}, 
32  *            {kLedAdsl,      kLedStateOff,       GPIO_LED_PIN_8},
33  *            {kLedPPP,       kLedStateOff,       GPIO_LED_PIN_9},    // PPP and WanData share PIN_9
34  *            {kLedWanData,   kLedStateOff,       GPIO_LED_PIN_9},
35  *            {kLedWireless,  kLedStateOff,       GPIO_LED_PIN_10},
36  *            {kLedEnd,       kLedStateOff,       0              } // NOTE: kLedEnd has to be at the end.
37  *
38  *    2). };To initialize led API and initial state of the leds, call the following function with the mapping 
39  *        pointer from the above struct
40  *
41  *        boardLedInit((PLED_MAP_PAIR) &cLedMapping45R);
42  *
43  *    3). Sample call for kernel mode:
44  *
45  *        kerSysLedCtrl(kLedAdsl, kLedStateBlinkOnce);        // kLedxxx defines in board.h
46  *
47  *    4). Sample call for user mode
48  *
49  *        sysLedCtrl(kLedAdsl, kLedStateBlinkOnce);           // kLedxxx defines in board_api.h
50  *
51  *
52  * Created on :  10/28/2002  seanl
53  *
54  ***************************************************************************/
55
56 /* Includes. */
57 #include <linux/init.h>
58 #include <linux/fs.h>
59 #include <linux/capability.h>
60 #include <linux/slab.h>
61 #include <linux/errno.h>
62 #include <linux/module.h>
63 #include <linux/netdevice.h>
64 #include <asm/uaccess.h>
65
66 #include <bcm_map_part.h>
67 #include <board.h>
68
69 #define k125ms              (HZ / 8)   // ~125 ms
70 #define kFastBlinkCount     0          // ~125ms
71 #define kSlowBlinkCount     1          // ~250ms
72
73 #define MAX_VIRT_LEDS       12
74
75 // uncomment // for debug led
76 //#define DEBUG_LED
77
78 // global variables:
79 struct timer_list gLedTimer, gBlinkOnceTimer;
80 int gTimerOn = FALSE;
81 int gBlinkOnceTimerOn = FALSE;
82 int gLedCount = 0;
83
84 typedef struct ledinfo
85 {
86     unsigned long ledMask;          // mask for led: ie. giop 10 = 0x0400
87     unsigned short ledActiveLow;    // GPIO bit reset to turn on LED
88     unsigned short ledSerial;       // indicated that LED is driven via serial output
89     unsigned long ledMaskFail;      // mask for led: ie. giop 10 = 0x0400
90     unsigned short ledActiveLowFail;// GPIO bit reset to turn on LED
91     unsigned short ledSerialFail;   // indicated that LED is driven via serial output
92     BOARD_LED_STATE ledState;       // current led state
93     BOARD_LED_STATE savedLedState;  // used in blink once for restore to the orignal ledState
94     int blinkCountDown;             // if == 0, do blink (toggle).  Is assgined value and dec by 1 at each timer.
95 } LED_INFO, *PLED_INFO;
96
97 static PLED_INFO gLed = NULL;
98 static PLED_INFO gpVirtLeds[MAX_VIRT_LEDS];
99 static HANDLE_LED_FUNC gLedHwFunc[MAX_VIRT_LEDS];
100 static HANDLE_LED_FUNC gLedHwFailFunc[MAX_VIRT_LEDS];
101
102 void blinkOnceTimerExpire(void); // Keven
103 void ledTimerExpire(void);
104 int initLedInfo( PLED_MAP_PAIR pCurMap, PLED_INFO pCurLed );
105
106 //**************************************************************************************
107 // LED operations
108 //**************************************************************************************
109
110 // turn led on and set the ledState
111 void ledOn(PLED_INFO pLed)
112 {
113     if( pLed->ledMask )
114     {
115         if (pLed->ledSerial) {
116 #if defined(CONFIG_BCM96358)
117             while (GPIO->SerialLedCtrl & SER_LED_BUSY);
118             if( pLed->ledActiveLow )
119                 GPIO->SerialLed  &= ~pLed->ledMask;    // turn on the led
120             else
121                 GPIO->SerialLed  |= pLed->ledMask;     // turn on the led
122 #endif
123         }
124         else {
125             GPIO->GPIODir |= pLed->ledMask;         // turn on the direction bit in case was turned off by some one
126             if( pLed->ledActiveLow )
127                 GPIO->GPIOio  &= ~pLed->ledMask;    // turn on the led
128             else
129                 GPIO->GPIOio  |= pLed->ledMask;     // turn on the led
130         }
131         pLed->ledState = pLed->savedLedState = kLedStateOn;
132     }
133 }
134
135
136 // turn led off and set the ledState
137 void ledOff(PLED_INFO pLed)
138 {
139     if( pLed->ledMask )
140     {
141         if (pLed->ledSerial) {
142 #if defined(CONFIG_BCM96358)
143             while (GPIO->SerialLedCtrl & SER_LED_BUSY);
144             if( pLed->ledActiveLow )
145                 GPIO->SerialLed  |= pLed->ledMask;     // turn off the led
146             else
147                 GPIO->SerialLed  &= ~pLed->ledMask;    // turn off the led
148 #endif
149         }
150         else {
151             GPIO->GPIODir |= pLed->ledMask;         // turn on the direction bit in case was turned off by some one
152             if( pLed->ledActiveLow )
153                 GPIO->GPIOio  |= pLed->ledMask;     // turn off the led
154             else
155                 GPIO->GPIOio  &= ~pLed->ledMask;    // turn off the led
156         }
157         pLed->ledState = pLed->savedLedState = kLedStateOff;
158     }
159 }
160
161 // turn led on and set the ledState
162 void ledOnFail(PLED_INFO pLed)
163 {
164     if( pLed->ledMaskFail )
165     {
166         if (pLed->ledSerialFail) {
167 #if defined(CONFIG_BCM96358)
168             while (GPIO->SerialLedCtrl & SER_LED_BUSY);
169             if( pLed->ledActiveLowFail )
170                 GPIO->SerialLed  &= ~pLed->ledMaskFail;    // turn on the led
171             else
172                 GPIO->SerialLed  |= pLed->ledMaskFail;     // turn on the led
173 #endif
174         }
175         else {
176             GPIO->GPIODir |= pLed->ledMaskFail;     // turn on the direction bit in case was turned off by some one
177             if( pLed->ledActiveLowFail )
178                 GPIO->GPIOio  &= ~pLed->ledMaskFail;// turn on the led
179             else
180                 GPIO->GPIOio  |= pLed->ledMaskFail; // turn on the led
181         }
182         pLed->ledState = pLed->savedLedState = kLedStateFail;
183     }
184 }
185
186
187 // turn led off and set the ledState
188 void ledOffFail(PLED_INFO pLed)
189 {
190     if( pLed->ledMaskFail )
191     {
192         if (pLed->ledSerialFail) {
193 #if defined(CONFIG_BCM96358)
194             while (GPIO->SerialLedCtrl & SER_LED_BUSY);
195             if( pLed->ledActiveLowFail )
196                 GPIO->SerialLed  |= pLed->ledMaskFail;     // turn off the led
197             else
198                 GPIO->SerialLed  &= ~pLed->ledMaskFail;    // turn off the led
199 #endif
200         }
201         else {
202             GPIO->GPIODir |= pLed->ledMaskFail;     // turn on the direction bit in case was turned off by some one
203             if( pLed->ledActiveLowFail )
204                 GPIO->GPIOio  |= pLed->ledMaskFail; // turn off the led
205             else
206                 GPIO->GPIOio  &= ~pLed->ledMaskFail;// turn off the led
207         }
208         pLed->ledState = pLed->savedLedState = kLedStateOff;
209     }
210 }
211
212
213 // toggle the led and return the current ledState
214 BOARD_LED_STATE ledToggle(PLED_INFO pLed)
215 {
216     if (pLed->ledSerial) {
217 #if defined(CONFIG_BCM96358)
218         while (GPIO->SerialLedCtrl & SER_LED_BUSY);
219         if (GPIO->SerialLed & pLed->ledMask)
220         {
221             GPIO->SerialLed &= ~(pLed->ledMask);
222             return( (pLed->ledActiveLow) ? kLedStateOn : kLedStateOff );
223         }
224         else
225         {
226             GPIO->SerialLed |= pLed->ledMask;
227             return( (pLed->ledActiveLow) ? kLedStateOff : kLedStateOn );
228         }
229 #endif
230     }
231     else {
232         GPIO->GPIODir |= pLed->ledMask;         // turn on the direction bit in case was turned off by some one
233         if (GPIO->GPIOio & pLed->ledMask)
234         {
235             GPIO->GPIOio &= ~(pLed->ledMask);
236             return( (pLed->ledActiveLow) ? kLedStateOn : kLedStateOff );
237         }
238         else
239         {
240             GPIO->GPIOio |= pLed->ledMask;
241             return( (pLed->ledActiveLow) ? kLedStateOff : kLedStateOn );
242         }
243     }
244 }   
245
246 // Keven -- LED BlinkOnce timer 
247 void blinkOnceTimerStart(void)
248 {
249     if(gBlinkOnceTimerOn)
250        return;
251
252     init_timer(&gBlinkOnceTimer);
253     gBlinkOnceTimer.function = (void*)blinkOnceTimerExpire;
254     gBlinkOnceTimer.expires = jiffies + k125ms; 
255     add_timer(&gBlinkOnceTimer);
256     gBlinkOnceTimerOn = TRUE;
257 }
258
259 void blinkOnceTimerExpire(void)
260 {
261     gBlinkOnceTimerOn = FALSE;
262 }
263
264 // led timer.  Will return if timer is already on
265 void ledTimerStart(void)
266 {
267     if (gTimerOn)
268         return;
269
270 #if defined(DEBUG_LED)
271     printk("led: add_timer\n");
272 #endif
273
274     init_timer(&gLedTimer);
275     gLedTimer.function = (void*)ledTimerExpire;
276     gLedTimer.expires = jiffies + k125ms;        // timer expires in ~100ms
277     add_timer (&gLedTimer);
278     gTimerOn = TRUE;
279
280
281
282 // led timer expire kicks in about ~100ms and perform the led operation according to the ledState and
283 // restart the timer according to ledState
284 void ledTimerExpire(void)
285 {
286     int i;
287     PLED_INFO pCurLed;
288
289     gTimerOn = FALSE;
290
291     for (i = 0, pCurLed = gLed; i < gLedCount; i++, pCurLed++)
292     {
293 #if defined(DEBUG_LED)
294         printk("led[%d]: Mask=0x%04x, State = %d, blcd=%d\n", i, pCurLed->ledMask, pCurLed->ledState, pCurLed->blinkCountDown);
295 #endif
296         switch (pCurLed->ledState)
297         {
298             case kLedStateOn:
299             case kLedStateOff:
300             case kLedStateFail:
301                 pCurLed->blinkCountDown = 0;            // reset the blink count down
302                 break;
303
304             case kLedStateBlinkOnce:
305                 blinkOnceTimerStart();                            // Keven -- Start BlinkOnceTimer
306                 ledToggle(pCurLed);
307                 pCurLed->blinkCountDown = 0;                      // reset to 0
308                 pCurLed->ledState = pCurLed->savedLedState;
309                 if (pCurLed->ledState == kLedStateSlowBlinkContinues || 
310                     pCurLed->ledState == kLedStateFastBlinkContinues)
311                     ledTimerStart();                  // start timer if in blinkContinues stats
312                 break;
313
314             case kLedStateSlowBlinkContinues:
315                 if (pCurLed->blinkCountDown-- == 0)
316                 {
317                     pCurLed->blinkCountDown = kSlowBlinkCount;
318                     ledToggle(pCurLed);
319                 }
320                 ledTimerStart();
321                 break;
322
323             case kLedStateFastBlinkContinues:
324                 if (pCurLed->blinkCountDown-- == 0)
325                 {
326                     pCurLed->blinkCountDown = kFastBlinkCount;
327                     ledToggle(pCurLed);
328                 }
329                 ledTimerStart();
330                 break;
331
332             default:
333                 printk("Invalid state = %d\n", pCurLed->ledState);
334         }
335     }
336 }
337
338 // initialize the gLedCount and allocate and fill gLed struct
339 void __init boardLedInit(PLED_MAP_PAIR cLedMapping)
340 {
341     PLED_MAP_PAIR p1, p2;
342     PLED_INFO pCurLed;
343     int needTimer = FALSE;
344     int alreadyUsed = 0;
345
346 #if defined(CONFIG_BCM96348) || defined(CONFIG_BCM96338) || defined(CONFIG_BCM96358)
347     /* Set blink rate for BCM6348/BCM6338 hardware LEDs. */
348     GPIO->LEDCtrl &= ~LED_INTERVAL_SET_MASK;
349     GPIO->LEDCtrl |= LED_INTERVAL_SET_80MS;
350 #endif
351 #if defined(CONFIG_BCM96358)
352 #ifdef BRCM_ORIGINAL    //swda modify,05/30/2006
353     /* Enable LED Outputs */
354     GPIO->GPIOMode |= GPIO_MODE_LED_OVERLAY;
355     GPIO->GPIODir |= 0x000f;
356     /* Enable Serial LED Outputs */
357     GPIO->GPIOMode |= GPIO_MODE_SERIAL_LED_OVERLAY;
358     GPIO->GPIODir |= 0x00c0;
359 #elif defined(IAD_VDSL_6358)
360         /* Disable LED Outputs, use standard GPIO defination */
361         GPIO->GPIOMode &= (~GPIO_MODE_LED_OVERLAY);
362     /* Enable Serial LED Outputs */
363     GPIO->GPIOMode |= GPIO_MODE_SERIAL_LED_OVERLAY;
364     GPIO->GPIODir |= 0x00c0;//gpio6,7 were used to control serial led, so set gpio 6,7 as output pins
365         //turn off VOIP Led,SLIC_ACT1 Led,SLIC_ACT2 Led : Serial LED GPIO 5,6,7(active low)
366         while (GPIO->SerialLedCtrl & SER_LED_BUSY);
367         GPIO->SerialLed  |= 0x000000e0;
368 #elif defined(IAD_GPON_6358)
369         /* Disable LED Outputs, use standard GPIO defination */
370         GPIO->GPIOMode &= (~GPIO_MODE_LED_OVERLAY);
371         /* Disable Serial LED Outputs, use standard GPIO defination */
372         GPIO->GPIOMode &= (~GPIO_MODE_SERIAL_LED_OVERLAY);
373 #else
374         /* Disable LED Outputs, use standard GPIO defination */
375         GPIO->GPIOMode &= (~GPIO_MODE_LED_OVERLAY);
376         /* Disable Serial LED Outputs, use standard GPIO defination */
377         GPIO->GPIOMode &= (~GPIO_MODE_SERIAL_LED_OVERLAY);
378         printk("GPIO->GPIOMode = 0x%08X\n",GPIO->GPIOMode);
379         //turn off FXO Led  : GPIO 7(active low)
380         GPIO->GPIODir |= GPIO_NUM_TO_MASK(7);
381         GPIO->GPIOio |= GPIO_NUM_TO_MASK(7); 
382         //turn off VOIP Led : GPIO 15(active low)
383         GPIO->GPIODir |= GPIO_NUM_TO_MASK(15);
384         GPIO->GPIOio |= GPIO_NUM_TO_MASK(15);
385         //turn off SLIC_ACT1 Led: GPIO 26(active low)
386         GPIO->GPIODir |= GPIO_NUM_TO_MASK(26);
387         GPIO->GPIOio |= GPIO_NUM_TO_MASK(26);
388         //turn off SLIC_ACT2 Led: GPIO 6(active low)
389         GPIO->GPIODir |= GPIO_NUM_TO_MASK(6);
390         GPIO->GPIOio |= GPIO_NUM_TO_MASK(6);
391 #endif  //swda modify end
392 #endif
393
394     memset( gpVirtLeds, 0x00, sizeof(gpVirtLeds) );
395     memset( gLedHwFunc, 0x00, sizeof(gLedHwFunc) );
396     memset( gLedHwFailFunc, 0x00, sizeof(gLedHwFailFunc) );
397
398     gLedCount = 0;
399
400     // Check for multiple LED names and multiple LED GPIO pins that share the
401     // same physical board LED.
402     for( p1 = cLedMapping; p1->ledName != kLedEnd; p1++ )
403     {
404         alreadyUsed = 0;
405         for( p2 = cLedMapping; p2 != p1; p2++ )
406         {
407             if( (p1->ledMask && p1->ledMask == p2->ledMask) ||
408                 (p1->ledMaskFail && p1->ledMaskFail == p2->ledMaskFail) )
409             {
410                 alreadyUsed = 1;
411                 break;
412             }
413         }
414
415         if( alreadyUsed == 0  )
416             gLedCount++;
417     }
418
419     gLed = (PLED_INFO) kmalloc((gLedCount * sizeof(LED_INFO)), GFP_KERNEL);
420     if( gLed == NULL )
421     {
422         printk( "LED memory allocation error.\n" );
423         return;
424     }
425
426     memset( gLed, 0x00, gLedCount * sizeof(LED_INFO) );
427
428     // initial the gLed with unique ledMask and initial state. If more than 1 ledNames share the physical led 
429     // (ledMask) the first defined led's ledInitState will be used.
430     pCurLed = gLed;
431     for( p1 = cLedMapping; p1->ledName != kLedEnd; p1++ )
432     {
433         if( (int) p1->ledName > MAX_VIRT_LEDS )
434             continue;
435
436         alreadyUsed = 0;
437         for( p2 = cLedMapping; p2 != p1; p2++ )
438         {
439             if( (p1->ledMask && p1->ledMask == p2->ledMask) ||
440                 (p1->ledMaskFail && p1->ledMaskFail == p2->ledMaskFail) )
441             {
442                 alreadyUsed = 1;
443                 break;
444             }
445         }
446
447         if( alreadyUsed == 0 )
448         {
449             // Initialize the board LED for the first time.
450             needTimer = initLedInfo( p1, pCurLed );
451             gpVirtLeds[(int) p1->ledName] = pCurLed;
452             pCurLed++;
453         }
454         else
455         {
456             PLED_INFO pLed;
457             for( pLed = gLed; pLed != pCurLed; pLed++ )
458             {
459                 // Find the LED_INFO structure that has already been initialized.
460                 if((pLed->ledMask && pLed->ledMask == p1->ledMask) ||
461                    (pLed->ledMaskFail && pLed->ledMaskFail==p1->ledMaskFail))
462                 {
463                     // The board LED has already been initialized but possibly
464                     // not completely initialized.
465                     if( p1->ledMask )
466                     {
467                         pLed->ledMask = p1->ledMask;
468                         pLed->ledActiveLow = p1->ledActiveLow;
469                         pLed->ledSerial = p1->ledSerial;
470                     }
471                     if( p1->ledMaskFail )
472                     {
473                         pLed->ledMaskFail = p1->ledMaskFail;
474                         pLed->ledActiveLowFail = p1->ledActiveLowFail;
475                         pLed->ledSerialFail = p1->ledSerialFail;
476                     }
477                     gpVirtLeds[(int) p1->ledName] = pLed;
478                     break;
479                 }
480             }
481         }
482     }
483
484     if (needTimer)
485         ledTimerStart();
486
487 #if defined(DEBUG_LED)
488     int i;
489     for (i=0; i < gLedCount; i++)
490         printk("initLed: led[%d]: mask=0x%04x, state=%d\n", i,(gLed+i)->ledMask, (gLed+i)->ledState);
491 #endif
492
493 }
494
495 // Initialize a structure that contains information about a physical board LED
496 // control.  The board LED may contain more than one GPIO pin to control a
497 // normal condition (green) or a failure condition (red).
498 int initLedInfo( PLED_MAP_PAIR pCurMap, PLED_INFO pCurLed )
499 {
500     int needTimer = FALSE;
501     pCurLed->ledState = pCurLed->savedLedState = pCurMap->ledInitState;
502     pCurLed->ledMask = pCurMap->ledMask;
503     pCurLed->ledActiveLow = pCurMap->ledActiveLow;
504     pCurLed->ledSerial = pCurMap->ledSerial;
505     pCurLed->ledMaskFail = pCurMap->ledMaskFail;
506     pCurLed->ledActiveLowFail = pCurMap->ledActiveLowFail;
507     pCurLed->ledSerialFail = pCurMap->ledSerialFail;
508
509     switch (pCurLed->ledState)
510     {
511         case kLedStateOn:
512             pCurLed->blinkCountDown = 0;            // reset the blink count down
513             ledOn(pCurLed);
514             break;
515         case kLedStateOff:
516             pCurLed->blinkCountDown = 0;            // reset the blink count down
517             ledOff(pCurLed);
518             break;
519         case kLedStateFail:
520             pCurLed->blinkCountDown = 0;            // reset the blink count down
521             ledOnFail(pCurLed);
522             break;
523         case kLedStateBlinkOnce:
524             pCurLed->blinkCountDown = 1;
525             needTimer = TRUE;
526             break;
527         case kLedStateSlowBlinkContinues:
528             pCurLed->blinkCountDown = kSlowBlinkCount;
529             needTimer = TRUE;
530             break;
531         case kLedStateFastBlinkContinues:
532             pCurLed->blinkCountDown = kFastBlinkCount;
533             needTimer = TRUE;
534             break;
535         default:
536             printk("Invalid state = %d\n", pCurLed->ledState);
537     }
538
539     return( needTimer );
540 }
541
542 // led ctrl.  Maps the ledName to the corresponding ledInfoPtr and perform the led operation
543 void boardLedCtrl(BOARD_LED_NAME ledName, BOARD_LED_STATE ledState)
544 {
545     PLED_INFO ledInfoPtr;
546
547     // do the mapping from virtual to physical led
548     if( (int) ledName < MAX_VIRT_LEDS )
549         ledInfoPtr = gpVirtLeds[(int) ledName];
550     else
551         ledInfoPtr = NULL;
552
553     if( ledState != kLedStateFail && gLedHwFunc[(int) ledName] )
554     {
555         // First, turn off the complimentary (failure) LED.
556         if( gLedHwFailFunc[(int) ledName] )
557             (*gLedHwFailFunc[(int) ledName]) (ledName, kLedStateOff);
558         else
559             if( ledInfoPtr )
560                 ledOffFail(ledInfoPtr);
561
562         // Call function to handle hardware LED.
563         (*gLedHwFunc[(int) ledName]) (ledName, ledState);
564         return;
565     }
566     else
567         if( ledState == kLedStateFail && gLedHwFailFunc[(int) ledName] )
568         {
569             // First, turn off the complimentary (normal) LED.
570             if( gLedHwFunc[(int) ledName] )
571                 (*gLedHwFunc[(int) ledName]) (ledName, kLedStateOff);
572             else
573                 if( ledInfoPtr )
574                     ledOff(ledInfoPtr);
575
576             // Call function to handle hardware LED.
577             (*gLedHwFailFunc[(int) ledName]) (ledName, ledState);
578             return;
579         }
580
581     if (ledInfoPtr == NULL)
582         return;
583
584     // If the state is kLedStateFail and there is not a failure LED defined
585     // in the board parameters, change the state to kLedStateSlowBlinkContinues.
586     if( ledState == kLedStateFail && ledInfoPtr->ledMaskFail == 0 )
587         //ledState = kLedStateSlowBlinkContinues;//swda remove,05/03/2005
588         ledState = kLedStateOff;//swda add,05/03/2005
589     switch (ledState)
590     {
591         case kLedStateOn:
592             // First, turn off the complimentary (failure) LED GPIO.
593             if( ledInfoPtr->ledMaskFail )
594                 ledOffFail(ledInfoPtr);
595             else
596                 if( gLedHwFailFunc[(int) ledName] )
597                     (*gLedHwFailFunc[(int) ledName]) (ledName, kLedStateOff);
598
599             // Next, turn on the specified LED GPIO.
600             ledOn(ledInfoPtr);
601             break;
602
603         case kLedStateOff: 
604             // First, turn off the complimentary (failure) LED GPIO.
605             if( ledInfoPtr->ledMaskFail )
606                 ledOffFail(ledInfoPtr);
607             else
608                 if( gLedHwFailFunc[(int) ledName] )
609                     (*gLedHwFailFunc[(int) ledName]) (ledName, kLedStateOff);
610
611             // Next, turn off the specified LED GPIO.
612             ledOff(ledInfoPtr);
613             break;
614
615         case kLedStateFail:
616             // First, turn off the complimentary (normal) LED GPIO.
617             if( ledInfoPtr->ledMask )
618                 ledOff(ledInfoPtr);
619             else
620                 if( gLedHwFunc[(int) ledName] )
621                     (*gLedHwFunc[(int) ledName]) (ledName, kLedStateOff);
622
623             // Next, turn on (red) the specified LED GPIO.
624             ledOnFail(ledInfoPtr);
625             break;
626
627         case kLedStateBlinkOnce:
628             // skip blinkOnce if it is already in Slow/Fast blink continues state
629             if (ledInfoPtr->savedLedState == kLedStateSlowBlinkContinues ||
630                 ledInfoPtr->savedLedState == kLedStateFastBlinkContinues)
631                 ;
632             else
633             {
634                 if ( ledInfoPtr->blinkCountDown ||  // skip the call if it is 1
635                      gBlinkOnceTimerOn            ) // Keven -- skip the call if BlinkOnceTimer is on
636                     ;
637                 else
638                 {
639                     ledToggle(ledInfoPtr);
640                     ledInfoPtr->blinkCountDown = 1;  // it will be reset to 0 when timer expires
641                     ledInfoPtr->ledState = kLedStateBlinkOnce;
642                     ledTimerStart();
643                 }
644             }
645             break;
646
647         case kLedStateSlowBlinkContinues:
648             ledInfoPtr->blinkCountDown = kSlowBlinkCount;
649             ledInfoPtr->ledState = kLedStateSlowBlinkContinues;
650             ledInfoPtr->savedLedState = kLedStateSlowBlinkContinues;
651             ledTimerStart();
652             break;
653
654         case kLedStateFastBlinkContinues:
655             ledInfoPtr->blinkCountDown = kFastBlinkCount;
656             ledInfoPtr->ledState = kLedStateFastBlinkContinues;
657             ledInfoPtr->savedLedState = kLedStateFastBlinkContinues;
658             ledTimerStart();
659             break;
660
661         default:
662             printk("Invalid led state\n");
663     }
664 }
665
666 // This function is called for an LED that is controlled by hardware.
667 void kerSysLedRegisterHwHandler( BOARD_LED_NAME ledName,
668     HANDLE_LED_FUNC ledHwFunc, int ledFailType )
669 {
670     if( (int) ledName < MAX_VIRT_LEDS )
671     {
672         if( ledFailType == 1 )
673             gLedHwFailFunc[(int) ledName] = ledHwFunc;
674         else
675             gLedHwFunc[(int) ledName] = ledHwFunc;
676     }
677 }
678