www.usr.com/support/gpl/USR9107_release.1.4.tar.gz
[bcm963xx.git] / bcmdrivers / opensource / char / board / bcm963xx / impl1 / board.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  : board.c
21  *
22  * Description: This file contains Linux character device driver entry 
23  *              for the board related ioctl calls: flash, get free kernel
24  *              page and dump kernel memory, etc.
25  *
26  * Created on :  2/20/2002  seanl:  use cfiflash.c, cfliflash.h (AMD specific)
27  *
28  ***************************************************************************/
29
30
31 /* Includes. */
32 #include <linux/version.h>
33 #include <linux/init.h>
34 #include <linux/fs.h>
35 #include <linux/interrupt.h>
36 #include <linux/capability.h>
37 #include <linux/slab.h>
38 #include <linux/errno.h>
39 #include <linux/module.h>
40 #include <linux/pagemap.h>
41 #include <asm/uaccess.h>
42 #include <linux/wait.h>
43 #include <linux/poll.h>
44 #include <linux/sched.h>
45 #include <linux/list.h>
46 #include <linux/if.h>
47
48 #include <bcm_map_part.h>
49 #include <board.h>
50 #include <bcmTag.h>
51 #include "boardparms.h"
52 #include "flash_api.h"
53 #include "bcm_intr.h"
54 #include "board.h"
55 #include "bcm_map_part.h"
56
57 /* Typedefs. */
58
59 #if defined (WIRELESS)
60 #define SES_BTN_PRESSED 0x00000001
61 #define SES_EVENTS      SES_BTN_PRESSED /*OR all values if any*/
62 #define SES_LED_OFF     0
63 #define SES_LED_ON      1
64 #define SES_LED_BLINK   2
65 #endif
66
67 typedef struct
68 {
69     unsigned long ulId;
70     char chInUse;
71     char chReserved[3];
72 } MAC_ADDR_INFO, *PMAC_ADDR_INFO;
73
74 typedef struct
75 {
76     unsigned long ulSdramSize;
77     unsigned long ulPsiSize;
78     unsigned long ulNumMacAddrs;
79     unsigned char ucaBaseMacAddr[NVRAM_MAC_ADDRESS_LEN];
80     char chCountry[4];  // USR9108
81     MAC_ADDR_INFO MacAddrs[1];
82 } NVRAM_INFO, *PNVRAM_INFO;
83
84 typedef struct
85 {
86     unsigned long eventmask;    
87 } BOARD_IOC, *PBOARD_IOC;
88
89
90 /*Dyinggasp callback*/
91 typedef void (*cb_dgasp_t)(void *arg);
92 typedef struct _CB_DGASP__LIST
93 {
94     struct list_head list;
95     char name[IFNAMSIZ];
96     cb_dgasp_t cb_dgasp_fn;
97     void *context;
98 }CB_DGASP_LIST , *PCB_DGASP_LIST;
99
100
101 static LED_MAP_PAIR LedMapping[] =
102 {   // led name     Initial state       physical pin (ledMask)
103     {kLedEnd,       kLedStateOff,       0, 0, 0, 0},
104     {kLedEnd,       kLedStateOff,       0, 0, 0, 0},
105     {kLedEnd,       kLedStateOff,       0, 0, 0, 0},
106     {kLedEnd,       kLedStateOff,       0, 0, 0, 0},
107     {kLedEnd,       kLedStateOff,       0, 0, 0, 0},
108     {kLedEnd,       kLedStateOff,       0, 0, 0, 0}, 
109     {kLedEnd,       kLedStateOff,       0, 0, 0, 0}, 
110     {kLedEnd,       kLedStateOff,       0, 0, 0, 0},     
111     {kLedEnd,       kLedStateOff,       0, 0, 0, 0} // NOTE: kLedEnd has to be at the end.
112 };
113
114 /* Externs. */
115 extern struct file fastcall *fget_light(unsigned int fd, int *fput_needed);
116 extern unsigned int nr_free_pages (void);
117 extern const char *get_system_type(void);
118 extern void kerSysFlashInit(void);
119 extern unsigned long get_nvram_start_addr(void);
120 extern unsigned long get_scratch_pad_start_addr(void);
121 extern unsigned long getMemorySize(void);
122 extern void __init boardLedInit(PLED_MAP_PAIR);
123 extern void boardLedCtrl(BOARD_LED_NAME, BOARD_LED_STATE);
124 extern void kerSysLedRegisterHandler( BOARD_LED_NAME ledName,
125     HANDLE_LED_FUNC ledHwFunc, int ledFailType );
126 extern UINT32 getCrc32(byte *pdata, UINT32 size, UINT32 crc);
127
128 /* Prototypes. */
129 void __init InitNvramInfo( void );
130 static int board_open( struct inode *inode, struct file *filp );
131 static int board_ioctl( struct inode *inode, struct file *flip, unsigned int command, unsigned long arg );
132 static ssize_t board_read(struct file *filp,  char __user *buffer, size_t count, loff_t *ppos); 
133 static unsigned int board_poll(struct file *filp, struct poll_table_struct *wait);
134 static int board_release(struct inode *inode, struct file *filp);                        
135
136 static BOARD_IOC* borad_ioc_alloc(void);
137 static void borad_ioc_free(BOARD_IOC* board_ioc);
138
139 /* DyingGasp function prototype */
140 static void __init kerSysDyingGaspMapIntr(void);
141 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
142 static irqreturn_t kerSysDyingGaspIsr(int irq, void * dev_id, struct pt_regs * regs);
143 #else
144 static unsigned int kerSysDyingGaspIsr(void);
145 #endif
146 static void __init kerSysInitDyingGaspHandler( void );
147 static void __exit kerSysDeinitDyingGaspHandler( void );
148 /* -DyingGasp function prototype - */
149
150
151 #if defined (WIRELESS)
152 static irqreturn_t sesBtn_isr(int irq, void *dev_id, struct pt_regs *ptregs);
153 static void __init sesBtn_mapGpio(void);
154 static void __init sesBtn_mapIntr(int context);
155 static unsigned int sesBtn_poll(struct file *file, struct poll_table_struct *wait);
156 static ssize_t sesBtn_read(struct file *file,  char __user *buffer, size_t count, loff_t *ppos);
157 static void __init sesLed_mapGpio(void);
158 static void sesLed_ctrl(int action);
159 static void __init ses_board_init(void);
160 static void __exit ses_board_deinit(void);
161 #endif
162
163 static PNVRAM_INFO g_pNvramInfo = NULL;
164 static int g_ledInitialized = 0;
165 static wait_queue_head_t g_board_wait_queue;
166 static CB_DGASP_LIST *g_cb_dgasp_list_head = NULL;
167
168 static int g_wakeup_monitor = 0;
169 static struct file *g_monitor_file = NULL;
170 static struct task_struct *g_monitor_task = NULL;
171 static unsigned int (*g_orig_fop_poll)
172     (struct file *, struct poll_table_struct *) = NULL;
173
174 static struct file_operations board_fops =
175 {
176   open:       board_open,
177   ioctl:      board_ioctl,
178   poll:       board_poll,
179   read:       board_read,
180   release:    board_release,
181 };
182
183 uint32 board_major = 0;
184
185 #if defined (WIRELESS)
186 static unsigned short sesBtn_irq = BP_NOT_DEFINED;
187 static unsigned short sesBtn_gpio = BP_NOT_DEFINED;
188 static unsigned short sesLed_gpio = BP_NOT_DEFINED;
189 #endif
190
191 #if defined(MODULE)
192 int init_module(void)
193 {
194     return( brcm_board_init() );              
195 }
196
197 void cleanup_module(void)
198 {
199     if (MOD_IN_USE)
200         printk("brcm flash: cleanup_module failed because module is in use\n");
201     else
202         brcm_board_cleanup();
203 }
204 #endif //MODULE 
205
206
207
208 static int __init brcm_board_init( void )
209 {
210     typedef int (*BP_LED_FUNC) (unsigned short *);
211     static struct BpLedInformation
212     {
213         BOARD_LED_NAME ledName;
214         BP_LED_FUNC bpFunc;
215         BP_LED_FUNC bpFuncFail;
216     } bpLedInfo[] =
217     {{kLedAdsl, BpGetAdslLedGpio, BpGetAdslFailLedGpio},
218      {kLedWireless, BpGetWirelessLedGpio, NULL},
219      {kLedUsb, BpGetUsbLedGpio, NULL},
220      {kLedHpna, BpGetHpnaLedGpio, NULL},
221      {kLedWanData, BpGetWanDataLedGpio, NULL},
222      {kLedPPP, BpGetPppLedGpio, BpGetPppFailLedGpio},
223      {kLedVoip, BpGetVoipLedGpio, NULL},
224      {kLedSes, BpGetWirelessSesLedGpio, NULL},     
225      {kLedEnd, NULL, NULL}
226     };
227
228     int ret;
229         
230     ret = register_chrdev(BOARD_DRV_MAJOR, "bcrmboard", &board_fops );
231     if (ret < 0)
232         printk( "brcm_board_init(major %d): fail to register device.\n",BOARD_DRV_MAJOR);
233     else 
234     {
235         PLED_MAP_PAIR pLedMap = LedMapping;
236         unsigned short gpio;
237         struct BpLedInformation *pInfo;
238
239         printk("brcmboard: brcm_board_init entry\n");
240         board_major = BOARD_DRV_MAJOR;
241         InitNvramInfo();
242
243         for( pInfo = bpLedInfo; pInfo->ledName != kLedEnd; pInfo++ )
244         {
245             if( pInfo->bpFunc && (*pInfo->bpFunc) (&gpio) == BP_SUCCESS )
246             {
247                 pLedMap->ledName = pInfo->ledName;
248                 pLedMap->ledMask = GPIO_NUM_TO_MASK(gpio);
249                 pLedMap->ledActiveLow = (gpio & BP_ACTIVE_LOW) ? 1 : 0;
250             }
251             if( pInfo->bpFuncFail && (*pInfo->bpFuncFail) (&gpio) == BP_SUCCESS )
252             {
253                 pLedMap->ledName = pInfo->ledName;
254                 pLedMap->ledMaskFail = GPIO_NUM_TO_MASK(gpio);
255                 pLedMap->ledActiveLowFail = (gpio & BP_ACTIVE_LOW) ? 1 : 0;
256             }
257             if( pLedMap->ledName != kLedEnd )
258                 pLedMap++;
259         }
260         
261         init_waitqueue_head(&g_board_wait_queue);
262 #if defined (WIRELESS)
263         ses_board_init();
264 #endif        
265         kerSysInitDyingGaspHandler();
266         kerSysDyingGaspMapIntr();
267
268         boardLedInit(LedMapping);
269         g_ledInitialized = 1;
270     }
271
272     return ret;
273
274
275 void __init InitNvramInfo( void )
276 {
277     PNVRAM_DATA pNvramData = (PNVRAM_DATA) get_nvram_start_addr();
278     unsigned long ulNumMacAddrs = pNvramData->ulNumMacAddrs;
279
280     if( ulNumMacAddrs > 0 && ulNumMacAddrs <= NVRAM_MAC_COUNT_MAX )
281     {
282         unsigned long ulNvramInfoSize =
283             sizeof(NVRAM_INFO) + ((sizeof(MAC_ADDR_INFO) - 1) * ulNumMacAddrs);
284
285         g_pNvramInfo = (PNVRAM_INFO) kmalloc( ulNvramInfoSize, GFP_KERNEL );
286
287         if( g_pNvramInfo )
288         {
289             unsigned long ulPsiSize;
290             if( BpGetPsiSize( &ulPsiSize ) != BP_SUCCESS )
291                 ulPsiSize = NVRAM_PSI_DEFAULT;
292             memset( g_pNvramInfo, 0x00, ulNvramInfoSize );
293             g_pNvramInfo->ulPsiSize = ulPsiSize * 1024;
294             g_pNvramInfo->ulNumMacAddrs = pNvramData->ulNumMacAddrs;
295             memcpy( g_pNvramInfo->ucaBaseMacAddr, pNvramData->ucaBaseMacAddr,
296                 NVRAM_MAC_ADDRESS_LEN );
297             g_pNvramInfo->ulSdramSize = getMemorySize();
298             strcpy(g_pNvramInfo->chCountry, pNvramData->chCountry); //USR9108
299         }
300         else
301             printk("ERROR - Could not allocate memory for NVRAM data\n");
302     }
303     else
304         printk("ERROR - Invalid number of MAC addresses (%ld) is configured.\n",
305             ulNumMacAddrs);
306 }
307
308 void __exit brcm_board_cleanup( void )
309 {
310     printk("brcm_board_cleanup()\n");
311         
312     if (board_major != -1) 
313     {
314 #if defined (WIRELESS)          
315         ses_board_deinit();
316 #endif          
317         kerSysDeinitDyingGaspHandler();
318         unregister_chrdev(board_major, "board_ioctl");
319     }
320
321
322 static BOARD_IOC* borad_ioc_alloc(void)
323 {
324     BOARD_IOC *board_ioc =NULL;
325     board_ioc = (BOARD_IOC*) kmalloc( sizeof(BOARD_IOC) , GFP_KERNEL );
326     if(board_ioc)
327     {
328         memset(board_ioc, 0, sizeof(BOARD_IOC));
329     }
330     return board_ioc;
331 }
332
333 static void borad_ioc_free(BOARD_IOC* board_ioc)
334 {
335     if(board_ioc)
336     {
337         kfree(board_ioc);
338     }   
339 }
340
341
342 static int board_open( struct inode *inode, struct file *filp )
343 {
344     filp->private_data = borad_ioc_alloc();
345
346     if (filp->private_data == NULL)
347         return -ENOMEM;
348             
349     return( 0 );
350
351
352 static int board_release(struct inode *inode, struct file *filp)
353 {
354     BOARD_IOC *board_ioc = filp->private_data;
355     
356     wait_event_interruptible(g_board_wait_queue, 1);    
357     borad_ioc_free(board_ioc);
358
359     return( 0 );
360
361
362
363 static unsigned int board_poll(struct file *filp, struct poll_table_struct *wait)
364 {
365     unsigned int mask = 0;
366 #if defined (WIRELESS)          
367     BOARD_IOC *board_ioc = filp->private_data;          
368 #endif
369         
370     poll_wait(filp, &g_board_wait_queue, wait);
371 #if defined (WIRELESS)          
372     if(board_ioc->eventmask & SES_EVENTS){
373         mask |= sesBtn_poll(filp, wait);
374     }                   
375 #endif    
376
377     return mask;
378 }
379
380
381 static ssize_t board_read(struct file *filp,  char __user *buffer, size_t count, loff_t *ppos)
382 {
383 #if defined (WIRELESS)    
384     BOARD_IOC *board_ioc = filp->private_data;
385     if(board_ioc->eventmask & SES_EVENTS){
386         return sesBtn_read(filp, buffer, count, ppos);
387     }
388 #endif    
389     return 0;
390 }
391
392 //**************************************************************************************
393 // Utitlities for dump memory, free kernel pages, mips soft reset, etc.
394 //**************************************************************************************
395
396 /***********************************************************************
397  * Function Name: dumpaddr
398  * Description  : Display a hex dump of the specified address.
399  ***********************************************************************/
400 void dumpaddr( unsigned char *pAddr, int nLen )
401 {
402     static char szHexChars[] = "0123456789abcdef";
403     char szLine[80];
404     char *p = szLine;
405     unsigned char ch, *q;
406     int i, j;
407     unsigned long ul;
408
409     while( nLen > 0 )
410     {
411         sprintf( szLine, "%8.8lx: ", (unsigned long) pAddr );
412         p = szLine + strlen(szLine);
413
414         for(i = 0; i < 16 && nLen > 0; i += sizeof(long), nLen -= sizeof(long))
415         {
416             ul = *(unsigned long *) &pAddr[i];
417             q = (unsigned char *) &ul;
418             for( j = 0; j < sizeof(long); j++ )
419             {
420                 *p++ = szHexChars[q[j] >> 4];
421                 *p++ = szHexChars[q[j] & 0x0f];
422                 *p++ = ' ';
423             }
424         }
425
426         for( j = 0; j < 16 - i; j++ )
427             *p++ = ' ', *p++ = ' ', *p++ = ' ';
428
429         *p++ = ' ', *p++ = ' ', *p++ = ' ';
430
431         for( j = 0; j < i; j++ )
432         {
433             ch = pAddr[j];
434             *p++ = (ch > ' ' && ch < '~') ? ch : '.';
435         }
436
437         *p++ = '\0';
438         printk( "%s\r\n", szLine );
439
440         pAddr += i;
441     }
442     printk( "\r\n" );
443 } /* dumpaddr */
444
445
446 void kerSysMipsSoftReset(void)
447 {
448 #if defined(CONFIG_BCM96348)
449     if (PERF->RevID == 0x634800A1) {
450         typedef void (*FNPTR) (void);
451         FNPTR bootaddr = (FNPTR) FLASH_BASE;
452         int i;
453
454         /* Disable interrupts. */
455         cli();
456
457         /* Reset all blocks. */
458         PERF->BlockSoftReset &= ~BSR_ALL_BLOCKS;
459         for( i = 0; i < 1000000; i++ )
460             ;
461         PERF->BlockSoftReset |= BSR_ALL_BLOCKS;
462         /* Jump to the power on address. */
463         (*bootaddr) ();
464     }
465     else
466         PERF->pll_control |= SOFT_RESET;    // soft reset mips
467 #else
468     PERF->pll_control |= SOFT_RESET;    // soft reset mips
469 #endif
470 }
471
472
473 int kerSysGetMacAddress( unsigned char *pucaMacAddr, unsigned long ulId )
474 {
475     const unsigned long constMacAddrIncIndex = 3;
476     int nRet = 0;
477     PMAC_ADDR_INFO pMai = NULL;
478     PMAC_ADDR_INFO pMaiFreeNoId = NULL;
479     PMAC_ADDR_INFO pMaiFreeId = NULL;
480     unsigned long i = 0, ulIdxNoId = 0, ulIdxId = 0, baseMacAddr = 0;
481
482     /* baseMacAddr = last 3 bytes of the base MAC address treated as a 24 bit integer */
483     memcpy((unsigned char *) &baseMacAddr,
484         &g_pNvramInfo->ucaBaseMacAddr[constMacAddrIncIndex],
485         NVRAM_MAC_ADDRESS_LEN - constMacAddrIncIndex);
486     baseMacAddr >>= 8;
487
488     for( i = 0, pMai = g_pNvramInfo->MacAddrs; i < g_pNvramInfo->ulNumMacAddrs;
489         i++, pMai++ )
490     {
491         if( ulId == pMai->ulId || ulId == MAC_ADDRESS_ANY )
492         {
493             /* This MAC address has been used by the caller in the past. */
494             baseMacAddr = (baseMacAddr + i) << 8;
495             memcpy( pucaMacAddr, g_pNvramInfo->ucaBaseMacAddr,
496                 constMacAddrIncIndex);
497             memcpy( pucaMacAddr + constMacAddrIncIndex, (unsigned char *)
498                 &baseMacAddr, NVRAM_MAC_ADDRESS_LEN - constMacAddrIncIndex );
499             pMai->chInUse = 1;
500             pMaiFreeNoId = pMaiFreeId = NULL;
501             break;
502         }
503         else
504             if( pMai->chInUse == 0 )
505             {
506                 if( pMai->ulId == 0 && pMaiFreeNoId == NULL )
507                 {
508                     /* This is an available MAC address that has never been
509                      * used.
510                      */
511                     pMaiFreeNoId = pMai;
512                     ulIdxNoId = i;
513                 }
514                 else
515                     if( pMai->ulId != 0 && pMaiFreeId == NULL )
516                     {
517                         /* This is an available MAC address that has been used
518                          * before.  Use addresses that have never been used
519                          * first, before using this one.
520                          */
521                         pMaiFreeId = pMai;
522                         ulIdxId = i;
523                     }
524             }
525     }
526
527     if( pMaiFreeNoId || pMaiFreeId )
528     {
529         /* An available MAC address was found. */
530         memcpy(pucaMacAddr, g_pNvramInfo->ucaBaseMacAddr,NVRAM_MAC_ADDRESS_LEN);
531         if( pMaiFreeNoId )
532         {
533             baseMacAddr = (baseMacAddr + ulIdxNoId) << 8;
534             memcpy( pucaMacAddr, g_pNvramInfo->ucaBaseMacAddr,
535                 constMacAddrIncIndex);
536             memcpy( pucaMacAddr + constMacAddrIncIndex, (unsigned char *)
537                 &baseMacAddr, NVRAM_MAC_ADDRESS_LEN - constMacAddrIncIndex );
538             pMaiFreeNoId->ulId = ulId;
539             pMaiFreeNoId->chInUse = 1;
540         }
541         else
542         {
543             baseMacAddr = (baseMacAddr + ulIdxId) << 8;
544             memcpy( pucaMacAddr, g_pNvramInfo->ucaBaseMacAddr,
545                 constMacAddrIncIndex);
546             memcpy( pucaMacAddr + constMacAddrIncIndex, (unsigned char *)
547                 &baseMacAddr, NVRAM_MAC_ADDRESS_LEN - constMacAddrIncIndex );
548             pMaiFreeId->ulId = ulId;
549             pMaiFreeId->chInUse = 1;
550         }
551     }
552     else
553         if( i == g_pNvramInfo->ulNumMacAddrs )
554             nRet = -EADDRNOTAVAIL;
555
556     return( nRet );
557 } /* kerSysGetMacAddr */
558
559 int kerSysReleaseMacAddress( unsigned char *pucaMacAddr )
560 {
561     const unsigned long constMacAddrIncIndex = 3;
562     int nRet = -EINVAL;
563     unsigned long ulIdx = 0;
564     unsigned long baseMacAddr = 0;
565     unsigned long relMacAddr = 0;
566
567     /* baseMacAddr = last 3 bytes of the base MAC address treated as a 24 bit integer */
568     memcpy((unsigned char *) &baseMacAddr,
569         &g_pNvramInfo->ucaBaseMacAddr[constMacAddrIncIndex],
570         NVRAM_MAC_ADDRESS_LEN - constMacAddrIncIndex);
571     baseMacAddr >>= 8;
572
573     /* Get last 3 bytes of MAC address to release. */
574     memcpy((unsigned char *) &relMacAddr, &pucaMacAddr[constMacAddrIncIndex],
575         NVRAM_MAC_ADDRESS_LEN - constMacAddrIncIndex);
576     relMacAddr >>= 8;
577
578     ulIdx = relMacAddr - baseMacAddr;
579
580     if( ulIdx < g_pNvramInfo->ulNumMacAddrs )
581     {
582         PMAC_ADDR_INFO pMai = &g_pNvramInfo->MacAddrs[ulIdx];
583         if( pMai->chInUse == 1 )
584         {
585             pMai->chInUse = 0;
586             nRet = 0;
587         }
588     }
589
590     return( nRet );
591 } /* kerSysReleaseMacAddr */
592
593 int kerSysGetSdramSize( void )
594 {
595     return( (int) g_pNvramInfo->ulSdramSize );
596 } /* kerSysGetSdramSize */
597
598
599 void kerSysLedCtrl(BOARD_LED_NAME ledName, BOARD_LED_STATE ledState)
600 {
601     if (g_ledInitialized)
602       boardLedCtrl(ledName, ledState);
603 }
604
605 unsigned int kerSysMonitorPollHook( struct file *f, struct poll_table_struct *t)
606 {
607     int mask = (*g_orig_fop_poll) (f, t);
608
609     if( g_wakeup_monitor == 1 && g_monitor_file == f )
610     {
611         /* If g_wakeup_monitor is non-0, the user mode application needs to
612          * return from a blocking select function.  Return POLLPRI which will
613          * cause the select to return with the exception descriptor set.
614          */
615         mask |= POLLPRI;
616         g_wakeup_monitor = 0;
617     }
618
619     return( mask );
620 }
621
622 /* Put the user mode application that monitors link state on a run queue. */
623 void kerSysWakeupMonitorTask( void )
624 {
625     g_wakeup_monitor = 1;
626     if( g_monitor_task )
627         wake_up_process( g_monitor_task );
628 }
629
630 static PFILE_TAG getTagFromPartition(int imageNumber)
631 {
632     static unsigned char sectAddr1[sizeof(FILE_TAG)];
633     static unsigned char sectAddr2[sizeof(FILE_TAG)];
634     int blk = 0;
635     UINT32 crc;
636     PFILE_TAG pTag = NULL;
637     unsigned char *pBase = flash_get_memptr(0);
638     unsigned char *pSectAddr = NULL;
639
640     /* The image tag for the first image is always after the boot loader.
641      * The image tag for the second image, if it exists, is at one half
642      * of the flash size.
643      */
644     if( imageNumber == 1 )
645     {
646         blk = flash_get_blk((int) (pBase + FLASH_LENGTH_BOOT_ROM));
647         pSectAddr = sectAddr1;
648     }
649     else
650         if( imageNumber == 2 )
651         {
652             blk = flash_get_blk((int) (pBase + (flash_get_total_size() / 2)));
653             pSectAddr = sectAddr2;
654         }
655
656     if( blk )
657     {
658         memset(pSectAddr, 0x00, sizeof(FILE_TAG));
659         flash_read_buf((unsigned short) blk, 0, pSectAddr, sizeof(FILE_TAG));
660         crc = CRC32_INIT_VALUE;
661         crc = getCrc32(pSectAddr, (UINT32)TAG_LEN-TOKEN_LEN, crc);      
662         pTag = (PFILE_TAG) pSectAddr;
663         if (crc != (UINT32)(*(UINT32*)(pTag->tagValidationToken)))
664             pTag = NULL;
665     }
666
667     return( pTag );
668 }
669
670 static int getPartitionFromTag( PFILE_TAG pTag )
671 {
672     int ret = 0;
673
674     if( pTag )
675     {
676         PFILE_TAG pTag1 = getTagFromPartition(1);
677         PFILE_TAG pTag2 = getTagFromPartition(2);
678         int sequence = simple_strtoul(pTag->imageSequence,  NULL, 10);
679         int sequence1 = (pTag1) ? simple_strtoul(pTag1->imageSequence, NULL, 10)
680             : -1;
681         int sequence2 = (pTag2) ? simple_strtoul(pTag2->imageSequence, NULL, 10)
682             : -1;
683
684         if( pTag1 && sequence == sequence1 )
685             ret = 1;
686         else
687             if( pTag2 && sequence == sequence2 )
688                 ret = 2;
689     }
690
691     return( ret );
692 }
693
694 static PFILE_TAG getBootImageTag(void)
695 {
696     PFILE_TAG pTag = NULL;
697     PFILE_TAG pTag1 = getTagFromPartition(1);
698     PFILE_TAG pTag2 = getTagFromPartition(2);
699
700     if( pTag1 && pTag2 )
701     {
702         /* Two images are flashed. */
703         int sequence1 = simple_strtoul(pTag1->imageSequence, NULL, 10);
704         int sequence2 = simple_strtoul(pTag2->imageSequence, NULL, 10);
705         char *p;
706         char bootPartition = BOOT_LATEST_IMAGE;
707         NVRAM_DATA nvramData;
708
709         memcpy((char *) &nvramData, (char *) get_nvram_start_addr(),
710             sizeof(nvramData));
711         for( p = nvramData.szBootline; p[2] != '\0'; p++ )
712             if( p[0] == 'p' && p[1] == '=' )
713             {
714                 bootPartition = p[2];
715                 break;
716             }
717
718         if( bootPartition == BOOT_LATEST_IMAGE )
719             pTag = (sequence2 > sequence1) ? pTag2 : pTag1;
720         else /* Boot from the image configured. */
721             pTag = (sequence2 < sequence1) ? pTag2 : pTag1;
722     }
723     else
724         /* One image is flashed. */
725         pTag = (pTag2) ? pTag2 : pTag1;
726
727     return( pTag );
728 }
729
730 static void UpdateImageSequenceNumber( unsigned char *imageSequence )
731 {
732     int newImageSequence = 0;
733     PFILE_TAG pTag = getTagFromPartition(1);
734
735     if( pTag )
736         newImageSequence = simple_strtoul(pTag->imageSequence, NULL, 10);
737
738     pTag = getTagFromPartition(2);
739     if(pTag && simple_strtoul(pTag->imageSequence, NULL, 10) > newImageSequence)
740         newImageSequence = simple_strtoul(pTag->imageSequence, NULL, 10);
741
742     newImageSequence++;
743     sprintf(imageSequence, "%d", newImageSequence);
744 }
745
746 static int flashFsKernelImage( int destAddr, unsigned char *imagePtr,
747     int imageLen )
748 {
749     int status = 0;
750     PFILE_TAG pTag = (PFILE_TAG) imagePtr;
751     int rootfsAddr = simple_strtoul(pTag->rootfsAddress, NULL, 10) + BOOT_OFFSET;
752     int kernelAddr = simple_strtoul(pTag->kernelAddress, NULL, 10) + BOOT_OFFSET;
753     char *p;
754     char *tagFs = imagePtr;
755     unsigned int baseAddr = (unsigned int) flash_get_memptr(0);
756     unsigned int totalSize = (unsigned int) flash_get_total_size();
757     unsigned int availableSizeOneImg = totalSize -
758         ((unsigned int) rootfsAddr - baseAddr) - FLASH_RESERVED_AT_END;
759     unsigned int reserveForTwoImages =
760         (FLASH_LENGTH_BOOT_ROM > FLASH_RESERVED_AT_END)
761         ? FLASH_LENGTH_BOOT_ROM : FLASH_RESERVED_AT_END;
762     unsigned int availableSizeTwoImgs =
763         (totalSize / 2) - reserveForTwoImages;
764     unsigned int newImgSize = simple_strtoul(pTag->rootfsLen, NULL, 10) +
765         simple_strtoul(pTag->kernelLen, NULL, 10);
766     PFILE_TAG pCurTag = getBootImageTag();
767     UINT32 crc = CRC32_INIT_VALUE;
768     unsigned int curImgSize = 0;
769     NVRAM_DATA nvramData;
770
771     memcpy((char *)&nvramData, (char *)get_nvram_start_addr(),sizeof(nvramData));
772
773     if( pCurTag )
774     {
775         curImgSize = simple_strtoul(pCurTag->rootfsLen, NULL, 10) +
776             simple_strtoul(pCurTag->kernelLen, NULL, 10);
777     }
778
779     if( newImgSize > availableSizeOneImg)
780     {
781         printk("Illegal image size %d.  Image size must not be greater "
782             "than %d.\n", newImgSize, availableSizeOneImg);
783         return -1;
784     }
785
786     if( getTagFromPartition(1) != NULL && getTagFromPartition(2) != NULL &&
787         newImgSize > availableSizeTwoImgs )
788     {
789         printk("Illegal image size %d.  Image size must not be greater "
790             "than %d.\n", newImgSize, availableSizeTwoImgs);
791         return -1;
792     }
793
794     // If the current image fits in half the flash space and the new
795     // image to flash also fits in half the flash space, then flash it
796     // in the partition that is not currently being used to boot from.
797     if( curImgSize <= availableSizeTwoImgs &&
798         newImgSize <= availableSizeTwoImgs &&
799         getPartitionFromTag( pCurTag ) == 1 )
800     {
801         // Update rootfsAddr to point to the second boot partition.
802         int offset = (totalSize / 2) + TAG_LEN;
803
804         sprintf(((PFILE_TAG) tagFs)->kernelAddress, "%lu",
805             (unsigned long) IMAGE_BASE + offset + (kernelAddr - rootfsAddr));
806         kernelAddr = baseAddr + offset + (kernelAddr - rootfsAddr);
807
808         sprintf(((PFILE_TAG) tagFs)->rootfsAddress, "%lu",
809             (unsigned long) IMAGE_BASE + offset);
810         rootfsAddr = baseAddr + offset;
811     }
812
813     UpdateImageSequenceNumber( ((PFILE_TAG) tagFs)->imageSequence );
814     crc = getCrc32((unsigned char *)tagFs, (UINT32)TAG_LEN-TOKEN_LEN, crc);      
815     *(unsigned long *) &((PFILE_TAG) tagFs)->tagValidationToken[0] = crc;
816
817     if( (status = kerSysBcmImageSet((rootfsAddr-TAG_LEN), tagFs,
818         TAG_LEN + newImgSize)) != 0 )
819     {
820         printk("Failed to flash root file system. Error: %d\n", status);
821         return status;
822     }
823
824     for( p = nvramData.szBootline; p[2] != '\0'; p++ )
825         if( p[0] == 'p' && p[1] == '=' && p[2] != BOOT_LATEST_IMAGE )
826         {
827             UINT32 crc = CRC32_INIT_VALUE;
828     
829             // Change boot partition to boot from new image.
830             p[2] = BOOT_LATEST_IMAGE;
831
832             nvramData.ulCheckSum = 0;
833             crc = getCrc32((char *)&nvramData, (UINT32) sizeof(NVRAM_DATA), crc);      
834             nvramData.ulCheckSum = crc;
835             kerSysNvRamSet( (char *) &nvramData, sizeof(nvramData), 0);
836             break;
837         }
838
839     return(status);
840 }
841
842 PFILE_TAG kerSysImageTagGet(void)
843 {
844     return( getBootImageTag() );
845 }
846
847
848 //********************************************************************************************
849 // misc. ioctl calls come to here. (flash, led, reset, kernel memory access, etc.)
850 //********************************************************************************************
851 static int board_ioctl( struct inode *inode, struct file *flip,
852                         unsigned int command, unsigned long arg )
853 {
854     int ret = 0;
855     BOARD_IOCTL_PARMS ctrlParms;
856     unsigned char ucaMacAddr[NVRAM_MAC_ADDRESS_LEN];
857
858     switch (command) 
859     {
860         case BOARD_IOCTL_FLASH_INIT:
861             // not used for now.  kerSysBcmImageInit();
862             break;
863
864
865         case BOARD_IOCTL_FLASH_WRITE:
866             if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0)
867             {
868                 NVRAM_DATA SaveNvramData;
869                 PNVRAM_DATA pNvramData = (PNVRAM_DATA) get_nvram_start_addr();
870
871                 switch (ctrlParms.action)
872                 {
873                     case SCRATCH_PAD:
874                         ret = kerSysScratchPadSet(ctrlParms.string, ctrlParms.buf, ctrlParms.offset);
875                         break;
876
877                     case PERSISTENT:
878                         ret = kerSysPersistentSet(ctrlParms.string, ctrlParms.strLen, ctrlParms.offset);
879                         break;
880                 
881                     case NVRAM:
882                         ret = kerSysNvRamSet(ctrlParms.string, ctrlParms.strLen, ctrlParms.offset);
883                         break;
884
885                     case BCM_IMAGE_CFE:
886                         if( ctrlParms.strLen <= 0 || ctrlParms.strLen > FLASH_LENGTH_BOOT_ROM )
887                         {
888                             printk("Illegal CFE size [%d]. Size allowed: [%d]\n",
889                                 ctrlParms.strLen, FLASH_LENGTH_BOOT_ROM);
890                             ret = -1;
891                             break;
892                         }
893
894                         // save NVRAM data into a local structure
895                         memcpy( &SaveNvramData, pNvramData, sizeof(NVRAM_DATA) );
896
897                         // set memory type field
898                         BpGetSdramSize( (unsigned long *) &ctrlParms.string[SDRAM_TYPE_ADDRESS_OFFSET] );
899
900                         ret = kerSysBcmImageSet(ctrlParms.offset + BOOT_OFFSET, ctrlParms.string, ctrlParms.strLen);
901
902                         // if nvram is not valid, restore the current nvram settings
903                         if( BpSetBoardId( pNvramData->szBoardId ) != BP_SUCCESS &&
904                             *(unsigned long *) pNvramData == NVRAM_DATA_ID )
905                         {
906                             kerSysNvRamSet((char *) &SaveNvramData, sizeof(SaveNvramData), 0);
907                         }
908                         break;
909                         
910                     case BCM_IMAGE_FS:
911                         if( (ret = flashFsKernelImage( ctrlParms.offset,
912                             ctrlParms.string, ctrlParms.strLen)) == 0 )
913                         {
914                             kerSysMipsSoftReset();
915                         }
916                         break;
917
918                     case BCM_IMAGE_KERNEL:  // not used for now.
919                         break;
920                     case BCM_IMAGE_WHOLE:
921                         if(ctrlParms.strLen <= 0)
922                         {
923                             printk("Illegal flash image size [%d].\n", ctrlParms.strLen);
924                             ret = -1;
925                             break;
926                         }
927
928                         // save NVRAM data into a local structure
929                         memcpy( &SaveNvramData, pNvramData, sizeof(NVRAM_DATA) );
930
931                         ret = kerSysBcmImageSet(ctrlParms.offset, ctrlParms.string, ctrlParms.strLen);
932
933                         // if nvram is not valid, restore the current nvram settings
934                         if( BpSetBoardId( pNvramData->szBoardId ) != BP_SUCCESS &&
935                             *(unsigned long *) pNvramData == NVRAM_DATA_ID )
936                         {
937                             kerSysNvRamSet((char *) &SaveNvramData, sizeof(SaveNvramData), 0);
938                         }
939
940                         kerSysMipsSoftReset();
941                         break;
942
943                     default:
944                         ret = -EINVAL;
945                         printk("flash_ioctl_command: invalid command %d\n", ctrlParms.action);
946                         break;
947                 }
948                 ctrlParms.result = ret;
949                 __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));
950             }
951             else
952                 ret = -EFAULT;
953             break;
954
955         case BOARD_IOCTL_FLASH_READ:
956             if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) 
957             {
958                 switch (ctrlParms.action)
959                 {
960                     case SCRATCH_PAD:
961                         ret = kerSysScratchPadGet(ctrlParms.string, ctrlParms.buf, ctrlParms.offset);
962                         break;
963
964                     case PERSISTENT:
965                         ret = kerSysPersistentGet(ctrlParms.string, ctrlParms.strLen, ctrlParms.offset);
966                         break;
967
968                     case NVRAM:
969                         ret = kerSysNvRamGet(ctrlParms.string, ctrlParms.strLen, ctrlParms.offset);
970                         break;
971
972                     case FLASH_SIZE:
973                         ret = kerSysFlashSizeGet();
974                         break;
975
976                     default:
977                         ret = -EINVAL;
978                         printk("Not supported.  invalid command %d\n", ctrlParms.action);
979                         break;
980                 }
981                 ctrlParms.result = ret;
982                 __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));
983             }
984             else
985                 ret = -EFAULT;
986             break;
987
988         case BOARD_IOCTL_GET_NR_PAGES:
989             ctrlParms.result = nr_free_pages() + get_page_cache_size();
990             __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));
991             ret = 0;
992             break;
993
994         case BOARD_IOCTL_DUMP_ADDR:
995             if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) 
996             {
997                 dumpaddr( (unsigned char *) ctrlParms.string, ctrlParms.strLen );
998                 ctrlParms.result = 0;
999                 __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));
1000                 ret = 0;
1001             }
1002             else
1003                 ret = -EFAULT;
1004             break;
1005
1006         case BOARD_IOCTL_SET_MEMORY:
1007             if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) 
1008             {
1009                 unsigned long  *pul = (unsigned long *)  ctrlParms.string;
1010                 unsigned short *pus = (unsigned short *) ctrlParms.string;
1011                 unsigned char  *puc = (unsigned char *)  ctrlParms.string;
1012                 switch( ctrlParms.strLen )
1013                 {
1014                     case 4:
1015                         *pul = (unsigned long) ctrlParms.offset;
1016                         break;
1017                     case 2:
1018                         *pus = (unsigned short) ctrlParms.offset;
1019                         break;
1020                     case 1:
1021                         *puc = (unsigned char) ctrlParms.offset;
1022                         break;
1023                 }
1024                 dumpaddr( (unsigned char *) ctrlParms.string, sizeof(long) );
1025                 ctrlParms.result = 0;
1026                 __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));
1027                 ret = 0;
1028             }
1029             else
1030                 ret = -EFAULT;
1031             break;
1032       
1033         case BOARD_IOCTL_MIPS_SOFT_RESET:
1034             kerSysMipsSoftReset();
1035             break;
1036
1037         case BOARD_IOCTL_LED_CTRL:
1038             if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) 
1039             {
1040                     kerSysLedCtrl((BOARD_LED_NAME)ctrlParms.strLen, (BOARD_LED_STATE)ctrlParms.offset);
1041                     ret = 0;
1042                 }
1043             break;
1044
1045         case BOARD_IOCTL_GET_ID:
1046             if (copy_from_user((void*)&ctrlParms, (void*)arg,
1047                 sizeof(ctrlParms)) == 0) 
1048             {
1049                 if( ctrlParms.string )
1050                 {
1051                     char *p = (char *) get_system_type();
1052                     if( strlen(p) + 1 < ctrlParms.strLen )
1053                         ctrlParms.strLen = strlen(p) + 1;
1054                     __copy_to_user(ctrlParms.string, p, ctrlParms.strLen);
1055                 }
1056
1057                 ctrlParms.result = 0;
1058                 __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms,
1059                     sizeof(BOARD_IOCTL_PARMS));
1060             }
1061             break;
1062
1063         case BOARD_IOCTL_GET_MAC_ADDRESS:
1064             if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) 
1065             {
1066                 ctrlParms.result = kerSysGetMacAddress( ucaMacAddr,
1067                     ctrlParms.offset );
1068
1069                 if( ctrlParms.result == 0 )
1070                 {
1071                     __copy_to_user(ctrlParms.string, ucaMacAddr,
1072                         sizeof(ucaMacAddr));
1073                 }
1074
1075                 __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms,
1076                     sizeof(BOARD_IOCTL_PARMS));
1077                 ret = 0;
1078             }
1079             else
1080                 ret = -EFAULT;
1081             break;
1082
1083         case BOARD_IOCTL_RELEASE_MAC_ADDRESS:
1084             if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) 
1085             {
1086                 if (copy_from_user((void*)ucaMacAddr, (void*)ctrlParms.string, \
1087                      NVRAM_MAC_ADDRESS_LEN) == 0) 
1088                 {
1089                     ctrlParms.result = kerSysReleaseMacAddress( ucaMacAddr );
1090                 }
1091                 else
1092                 {
1093                     ctrlParms.result = -EACCES;
1094                 }
1095
1096                 __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms,
1097                     sizeof(BOARD_IOCTL_PARMS));
1098                 ret = 0;
1099             }
1100             else
1101                 ret = -EFAULT;
1102             break;
1103
1104         case BOARD_IOCTL_GET_PSI_SIZE:
1105             ctrlParms.result = (int) g_pNvramInfo->ulPsiSize;
1106             __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));
1107             ret = 0;
1108             break;
1109
1110         case BOARD_IOCTL_GET_SDRAM_SIZE:
1111             ctrlParms.result = (int) g_pNvramInfo->ulSdramSize;
1112             __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));
1113             ret = 0;
1114             break;
1115
1116         case BOARD_IOCTL_GET_BASE_MAC_ADDRESS:
1117             if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) 
1118             {
1119                 __copy_to_user(ctrlParms.string, g_pNvramInfo->ucaBaseMacAddr, NVRAM_MAC_ADDRESS_LEN);
1120                 ctrlParms.result = 0;
1121
1122                 __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms,
1123                     sizeof(BOARD_IOCTL_PARMS));
1124                 ret = 0;
1125             }
1126             else
1127                 ret = -EFAULT;
1128             break;
1129
1130         case BOARD_IOCTL_GET_CHIP_ID:
1131             ctrlParms.result = (int) (PERF->RevID & 0xFFFF0000) >> 16;
1132             __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));
1133             ret = 0;
1134             break;
1135
1136         case BOARD_IOCTL_GET_NUM_ENET: {
1137             ETHERNET_MAC_INFO EnetInfos[BP_MAX_ENET_MACS];
1138             int i, numeth = 0;
1139             if (BpGetEthernetMacInfo(EnetInfos, BP_MAX_ENET_MACS) == BP_SUCCESS) {
1140             for( i = 0; i < BP_MAX_ENET_MACS; i++) {
1141                 if (EnetInfos[i].ucPhyType != BP_ENET_NO_PHY) {
1142                 numeth++;
1143                 }
1144             }
1145             ctrlParms.result = numeth;
1146             __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms,  sizeof(BOARD_IOCTL_PARMS));   
1147             ret = 0;
1148             }
1149                 else {
1150                     ret = -EFAULT;
1151                 }
1152                 break;
1153             }
1154
1155         case BOARD_IOCTL_GET_CFE_VER:
1156             if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) {
1157                 char *vertag =  (char *)(FLASH_BASE + CFE_VERSION_OFFSET);
1158                 if (ctrlParms.strLen < CFE_VERSION_SIZE) {
1159                     ctrlParms.result = 0;
1160                     __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));
1161                     ret = -EFAULT;
1162                 }
1163                 else if (strncmp(vertag, "cfe-v", 5)) { // no tag info in flash
1164                     ctrlParms.result = 0;
1165                     __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));
1166                     ret = 0;
1167                 }
1168                 else {
1169                     ctrlParms.result = 1;
1170                     __copy_to_user(ctrlParms.string, vertag+CFE_VERSION_MARK_SIZE, CFE_VERSION_SIZE);
1171                     __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));
1172                     ret = 0;
1173                 }
1174             }
1175             else {
1176                 ret = -EFAULT;
1177             }
1178             break;
1179
1180         case BOARD_IOCTL_GET_ENET_CFG:
1181             if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) {
1182                 ETHERNET_MAC_INFO EnetInfos[BP_MAX_ENET_MACS];
1183                 if (BpGetEthernetMacInfo(EnetInfos, BP_MAX_ENET_MACS) == BP_SUCCESS) {
1184                     if (ctrlParms.strLen == sizeof(EnetInfos)) {
1185                         __copy_to_user(ctrlParms.string, EnetInfos, sizeof(EnetInfos));
1186                         ctrlParms.result = 0;
1187                         __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));   
1188                         ret = 0;
1189                     } else
1190                             ret = -EFAULT;
1191                 }
1192                     else {
1193                         ret = -EFAULT;
1194                     }
1195                     break;
1196             }
1197             else {
1198                 ret = -EFAULT;
1199             }
1200             break;            
1201
1202 #if defined (WIRELESS)
1203         case BOARD_IOCTL_GET_WLAN_ANT_INUSE:
1204             if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) {
1205                 unsigned short antInUse = 0;
1206                 if (BpGetWirelessAntInUse(&antInUse) == BP_SUCCESS) {
1207                     if (ctrlParms.strLen == sizeof(antInUse)) {
1208                         __copy_to_user(ctrlParms.string, &antInUse, sizeof(antInUse));
1209                         ctrlParms.result = 0;
1210                         __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));   
1211                         ret = 0;
1212                     } else
1213                             ret = -EFAULT;
1214                 }
1215                 else {
1216                    ret = -EFAULT;
1217                 }
1218                 break;
1219             }
1220             else {
1221                 ret = -EFAULT;
1222             }
1223             break;            
1224 #endif            
1225         case BOARD_IOCTL_SET_TRIGGER_EVENT:
1226             if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) {                
1227                 BOARD_IOC *board_ioc = (BOARD_IOC *)flip->private_data;                 
1228                 ctrlParms.result = -EFAULT;
1229                 ret = -EFAULT;
1230                 if (ctrlParms.strLen == sizeof(unsigned long)) {                                            
1231                     board_ioc->eventmask |= *((int*)ctrlParms.string);                    
1232 #if defined (WIRELESS)                    
1233                     if((board_ioc->eventmask & SES_EVENTS)) {
1234                         if(sesBtn_irq != BP_NOT_DEFINED) {
1235                             BcmHalInterruptEnable(sesBtn_irq);
1236                             ctrlParms.result = 0;
1237                             ret = 0;
1238                         }                                                
1239                     } 
1240 #endif                                                
1241                     __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));                        
1242                 }
1243                 break;
1244             }
1245             else {
1246                 ret = -EFAULT;
1247             }
1248             break;                        
1249
1250         case BOARD_IOCTL_GET_TRIGGER_EVENT:
1251             if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) {
1252                 BOARD_IOC *board_ioc = (BOARD_IOC *)flip->private_data;
1253                 if (ctrlParms.strLen == sizeof(unsigned long)) {
1254                     __copy_to_user(ctrlParms.string, &board_ioc->eventmask, sizeof(unsigned long));
1255                     ctrlParms.result = 0;
1256                     __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));   
1257                     ret = 0;
1258                 } else
1259                     ret = -EFAULT;
1260
1261                 break;
1262             }
1263             else {
1264                 ret = -EFAULT;
1265             }
1266             break;                
1267             
1268         case BOARD_IOCTL_UNSET_TRIGGER_EVENT:
1269             if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) {
1270                 if (ctrlParms.strLen == sizeof(unsigned long)) {
1271                     BOARD_IOC *board_ioc = (BOARD_IOC *)flip->private_data;                     
1272                     board_ioc->eventmask &= (~(*((int*)ctrlParms.string)));                  
1273                     ctrlParms.result = 0;
1274                     __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));   
1275                     ret = 0;
1276                 } else
1277                     ret = -EFAULT;
1278
1279                 break;
1280             } 
1281             else {
1282                 ret = -EFAULT;
1283             }
1284             break;            
1285 #if defined (WIRELESS)
1286         case BOARD_IOCTL_SET_SES_LED:
1287             if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) {
1288                 if (ctrlParms.strLen == sizeof(int)) {
1289                     sesLed_ctrl(*(int*)ctrlParms.string);
1290                     ctrlParms.result = 0;
1291                     __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));   
1292                     ret = 0;
1293                 } else
1294                     ret = -EFAULT;
1295
1296                 break;
1297             }
1298             else {
1299                 ret = -EFAULT;
1300             }
1301             break;            
1302 #endif                                                            
1303         // USR9108 Wi-Fi Country selection
1304         case BOARD_IOCTL_GET_CNTRY_SEL:
1305             if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) 
1306             {
1307                 __copy_to_user(ctrlParms.string, g_pNvramInfo->chCountry, 4);
1308                 ctrlParms.result = 0;
1309
1310                 __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms,
1311                     sizeof(BOARD_IOCTL_PARMS));
1312                 ret = 0;
1313             }
1314             else
1315                 ret = -EFAULT;
1316             break;
1317
1318         case BOARD_IOCTL_SET_MONITOR_FD:
1319             if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) {
1320                 int fput_needed = 0;
1321
1322                 g_monitor_file = fget_light( ctrlParms.offset, &fput_needed );
1323                 if( g_monitor_file ) {
1324                     /* Hook this file descriptor's poll function in order to set
1325                      * the exception descriptor when there is a change in link
1326                      * state.
1327                      */
1328                     g_monitor_task = current;
1329                     g_orig_fop_poll = g_monitor_file->f_op->poll;
1330                     g_monitor_file->f_op->poll = kerSysMonitorPollHook;
1331                 }
1332             }
1333             break;
1334
1335         case BOARD_IOCTL_WAKEUP_MONITOR_TASK:
1336             kerSysWakeupMonitorTask();
1337             break;
1338
1339         default:
1340             ret = -EINVAL;
1341             ctrlParms.result = 0;
1342             printk("board_ioctl: invalid command %x, cmd %d .\n",command,_IOC_NR(command));
1343             break;
1344
1345   } /* switch */
1346
1347   return (ret);
1348
1349 } /* board_ioctl */
1350
1351 /***************************************************************************
1352  * SES Button ISR/GPIO/LED functions.
1353  ***************************************************************************/
1354 #if defined (WIRELESS) 
1355 static irqreturn_t sesBtn_isr(int irq, void *dev_id, struct pt_regs *ptregs)
1356 {   
1357 #if defined(_BCM96338_) || defined(CONFIG_BCM96338)
1358     unsigned long gpio_mask = GPIO_NUM_TO_MASK(sesBtn_gpio);
1359     volatile unsigned long *gpio_reg = &GPIO->GPIOio;
1360 #endif
1361 #if defined(_BCM96345_) || defined(CONFIG_BCM96345)
1362     unsigned short gpio_mask = GPIO_NUM_TO_MASK(sesBtn_gpio);
1363     volatile unsigned short *gpio_reg = &GPIO->GPIOio;
1364 #endif
1365 #if defined(_BCM96348_) || defined (CONFIG_BCM96348)
1366     unsigned long gpio_mask = GPIO_NUM_TO_MASK(sesBtn_gpio);
1367     volatile unsigned long *gpio_reg = &GPIO->GPIOio;
1368
1369     if( (sesBtn_gpio & ~BP_ACTIVE_MASK) >= 32 )
1370     {
1371         gpio_mask = GPIO_NUM_TO_MASK_HIGH(sesBtn_gpio);
1372         gpio_reg = &GPIO->GPIOio_high;
1373     }
1374 #endif 
1375                 
1376     if (!(*gpio_reg & gpio_mask)){
1377         wake_up_interruptible(&g_board_wait_queue);
1378         return IRQ_RETVAL(1);
1379     } else {
1380         return IRQ_RETVAL(0);           
1381     }
1382 }
1383
1384 static void __init sesBtn_mapGpio()
1385 {       
1386     if( BpGetWirelessSesBtnGpio(&sesBtn_gpio) == BP_SUCCESS )
1387     {
1388         printk("SES: Button GPIO 0x%x is enabled\n", sesBtn_gpio);    
1389     }
1390 }
1391
1392 static void __init sesBtn_mapIntr(int context)
1393 {       
1394     if( BpGetWirelessSesExtIntr(&sesBtn_irq) == BP_SUCCESS )
1395     {
1396         printk("SES: Button Interrupt 0x%x is enabled\n", sesBtn_irq);
1397     }
1398     else
1399         return;
1400             
1401     sesBtn_irq += INTERRUPT_ID_EXTERNAL_0;      
1402                 
1403     if (BcmHalMapInterrupt((FN_HANDLER)sesBtn_isr, context, sesBtn_irq)) {
1404         printk("SES: Interrupt mapping failed\n");
1405     }    
1406     BcmHalInterruptEnable(sesBtn_irq);
1407 }
1408
1409
1410 static unsigned int sesBtn_poll(struct file *file, struct poll_table_struct *wait)
1411 {
1412 #if defined(_BCM96338_) || defined(CONFIG_BCM96338)
1413     unsigned long gpio_mask = GPIO_NUM_TO_MASK(sesBtn_gpio);
1414     volatile unsigned long *gpio_reg = &GPIO->GPIOio;
1415 #endif
1416 #if defined(_BCM96345_) || defined(CONFIG_BCM96345)
1417     unsigned short gpio_mask = GPIO_NUM_TO_MASK(sesBtn_gpio);
1418     volatile unsigned short *gpio_reg = &GPIO->GPIOio;
1419 #endif
1420 #if defined(_BCM96348_) || defined (CONFIG_BCM96348)
1421     unsigned long gpio_mask = GPIO_NUM_TO_MASK(sesBtn_gpio);
1422     volatile unsigned long *gpio_reg = &GPIO->GPIOio;
1423
1424     if( (sesBtn_gpio & ~BP_ACTIVE_MASK) >= 32 )
1425     {
1426         gpio_mask = GPIO_NUM_TO_MASK_HIGH(sesBtn_gpio);
1427         gpio_reg = &GPIO->GPIOio_high;
1428     }
1429 #endif 
1430                 
1431     if (!(*gpio_reg & gpio_mask)){
1432         return POLLIN;
1433     }   
1434     return 0;
1435 }
1436
1437 static ssize_t sesBtn_read(struct file *file,  char __user *buffer, size_t count, loff_t *ppos)
1438 {
1439     volatile unsigned int event=0;
1440     ssize_t ret=0;      
1441
1442 #if defined(_BCM96338_) || defined (CONFIG_BCM96338)
1443     unsigned long gpio_mask = GPIO_NUM_TO_MASK(sesBtn_gpio);
1444     volatile unsigned long *gpio_reg = &GPIO->GPIOio;
1445 #endif
1446 #if defined(_BCM96345_) || defined (CONFIG_BCM96345)
1447     unsigned short gpio_mask = GPIO_NUM_TO_MASK(sesBtn_gpio);
1448     volatile unsigned short *gpio_reg = &GPIO->GPIOio;
1449 #endif
1450 #if defined(_BCM96348_) || defined (CONFIG_BCM96348)
1451     unsigned long gpio_mask = GPIO_NUM_TO_MASK(sesBtn_gpio);
1452     volatile unsigned long *gpio_reg = &GPIO->GPIOio;
1453     
1454     if( (sesBtn_gpio & ~BP_ACTIVE_MASK) >= 32 )
1455     {
1456         gpio_mask = GPIO_NUM_TO_MASK_HIGH(sesBtn_gpio);
1457         gpio_reg = &GPIO->GPIOio_high;
1458     }
1459 #endif 
1460
1461     if(*gpio_reg & gpio_mask){
1462         BcmHalInterruptEnable(sesBtn_irq);              
1463         return ret;
1464     }   
1465     event = SES_EVENTS;
1466     __copy_to_user((char*)buffer, (char*)&event, sizeof(event));        
1467     BcmHalInterruptEnable(sesBtn_irq);  
1468     count -= sizeof(event);
1469     buffer += sizeof(event);
1470     ret += sizeof(event);       
1471     return ret; 
1472 }
1473
1474 static void __init sesLed_mapGpio()
1475 {       
1476     if( BpGetWirelessSesBtnGpio(&sesLed_gpio) == BP_SUCCESS )
1477     {
1478         printk("SES: LED GPIO 0x%x is enabled\n", sesBtn_gpio);    
1479     }
1480 }
1481
1482 static void sesLed_ctrl(int action)
1483 {
1484
1485     //char status = ((action >> 8) & 0xff); /* extract status */
1486     //char event = ((action >> 16) & 0xff); /* extract event */        
1487     //char blinktype = ((action >> 24) & 0xff); /* extract blink type for SES_LED_BLINK  */
1488     
1489     BOARD_LED_STATE led;
1490     
1491     if(sesLed_gpio == BP_NOT_DEFINED)
1492         return;
1493         
1494     action &= 0xff; /* extract led */
1495
1496     //printk("blinktype=%d, event=%d, status=%d\n",(int)blinktype, (int)event, (int)status);
1497                 
1498     switch (action) 
1499     {
1500         case SES_LED_ON:
1501             //printk("SES: led on\n");
1502             led = kLedStateOn;                                          
1503             break;
1504         case SES_LED_BLINK:
1505             //printk("SES: led blink\n");
1506             led = kLedStateSlowBlinkContinues;                          
1507             break;
1508         case SES_LED_OFF:
1509             default:
1510             //printk("SES: led off\n");
1511             led = kLedStateOff;                                                 
1512     }   
1513     
1514     kerSysLedCtrl(kLedSes, led);
1515 }
1516
1517 static void __init ses_board_init()
1518 {
1519     sesBtn_mapGpio();
1520     sesBtn_mapIntr(0);
1521     sesLed_mapGpio();
1522 }
1523 static void __exit ses_board_deinit()
1524 {
1525     if(sesBtn_irq)
1526         BcmHalInterruptDisable(sesBtn_irq);
1527 }
1528 #endif
1529
1530 /***************************************************************************
1531  * Dying gasp ISR and functions.
1532  ***************************************************************************/
1533 #define KERSYS_DBG      printk
1534
1535 #if defined(CONFIG_BCM96345)
1536 #define CYCLE_PER_US    70
1537 #elif defined(CONFIG_BCM96348) || defined(CONFIG_BCM96338)
1538 /* The BCM6348 cycles per microsecond is really variable since the BCM6348
1539  * MIPS speed can vary depending on the PLL settings.  However, an appoximate
1540  * value of 120 will still work OK for the test being done.
1541  */
1542 #define CYCLE_PER_US    120
1543 #endif
1544 #define DG_GLITCH_TO    (100*CYCLE_PER_US)
1545  
1546 static void __init kerSysDyingGaspMapIntr()
1547 {
1548     unsigned long ulIntr;
1549         
1550 #if defined(CONFIG_BCM96348) || defined(_BCM96348_) || defined(CONFIG_BCM96338) || defined(_BCM96338_)
1551     if( BpGetAdslDyingGaspExtIntr( &ulIntr ) == BP_SUCCESS ) {
1552                 BcmHalMapInterrupt((FN_HANDLER)kerSysDyingGaspIsr, 0, INTERRUPT_ID_DG);
1553                 BcmHalInterruptEnable( INTERRUPT_ID_DG );
1554     }
1555 #elif defined(CONFIG_BCM96345) || defined(_BCM96345_)
1556     if( BpGetAdslDyingGaspExtIntr( &ulIntr ) == BP_SUCCESS ) {
1557         ulIntr += INTERRUPT_ID_EXTERNAL_0;
1558         BcmHalMapInterrupt((FN_HANDLER)kerSysDyingGaspIsr, 0, ulIntr);
1559         BcmHalInterruptEnable( ulIntr );
1560     }
1561 #endif
1562
1563
1564
1565 void kerSysSetWdTimer(ulong timeUs)
1566 {
1567         TIMER->WatchDogDefCount = timeUs * (FPERIPH/1000000);
1568         TIMER->WatchDogCtl = 0xFF00;
1569         TIMER->WatchDogCtl = 0x00FF;
1570 }
1571
1572 ulong kerSysGetCycleCount(void)
1573 {
1574     ulong cnt; 
1575 #ifdef _WIN32_WCE
1576     cnt = 0;
1577 #else
1578     __asm volatile("mfc0 %0, $9":"=d"(cnt));
1579 #endif
1580     return(cnt); 
1581 }
1582
1583 static Bool kerSysDyingGaspCheckPowerLoss(void)
1584 {
1585     ulong clk0;
1586     ulong ulIntr;
1587
1588     ulIntr = 0;
1589     clk0 = kerSysGetCycleCount();
1590
1591     UART->Data = 'D';
1592     UART->Data = '%';
1593     UART->Data = 'G';
1594
1595 #if defined(CONFIG_BCM96345)
1596     BpGetAdslDyingGaspExtIntr( &ulIntr );
1597
1598     do {
1599         ulong clk1;
1600         
1601         clk1 = kerSysGetCycleCount();           /* time cleared */
1602         /* wait a little to get new reading */
1603         while ((kerSysGetCycleCount()-clk1) < CYCLE_PER_US*2)
1604             ;
1605     } while ((0 == (PERF->ExtIrqCfg & (1 << (ulIntr + EI_STATUS_SHFT)))) && ((kerSysGetCycleCount() - clk0) < DG_GLITCH_TO));
1606
1607     if (PERF->ExtIrqCfg & (1 << (ulIntr + EI_STATUS_SHFT))) {   /* power glitch */
1608         BcmHalInterruptEnable( ulIntr + INTERRUPT_ID_EXTERNAL_0);
1609         KERSYS_DBG(" - Power glitch detected. Duration: %ld us\n", (kerSysGetCycleCount() - clk0)/CYCLE_PER_US);
1610         return 0;
1611     }
1612 #elif (defined(CONFIG_BCM96348) || defined(CONFIG_BCM96338)) && !defined(VXWORKS)
1613     do {
1614         ulong clk1;
1615         
1616         clk1 = kerSysGetCycleCount();           /* time cleared */
1617         /* wait a little to get new reading */
1618         while ((kerSysGetCycleCount()-clk1) < CYCLE_PER_US*2)
1619             ;
1620      } while ((PERF->IrqStatus & (1 << (INTERRUPT_ID_DG - INTERNAL_ISR_TABLE_OFFSET))) && ((kerSysGetCycleCount() - clk0) < DG_GLITCH_TO));
1621
1622     if (!(PERF->IrqStatus & (1 << (INTERRUPT_ID_DG - INTERNAL_ISR_TABLE_OFFSET)))) {
1623         BcmHalInterruptEnable( INTERRUPT_ID_DG );
1624         KERSYS_DBG(" - Power glitch detected. Duration: %ld us\n", (kerSysGetCycleCount() - clk0)/CYCLE_PER_US);
1625         return 0;
1626     }
1627 #endif
1628     return 1;
1629 }
1630
1631 static void kerSysDyingGaspShutdown( void )
1632 {
1633     kerSysSetWdTimer(1000000);
1634 #if defined(CONFIG_BCM96345)
1635     PERF->blkEnables &= ~(EMAC_CLK_EN | USB_CLK_EN | CPU_CLK_EN);   
1636 #elif defined(CONFIG_BCM96348)
1637     PERF->blkEnables &= ~(EMAC_CLK_EN | USBS_CLK_EN | USBH_CLK_EN | SAR_CLK_EN);
1638 #endif
1639 }
1640
1641 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
1642 static irqreturn_t kerSysDyingGaspIsr(int irq, void * dev_id, struct pt_regs * regs)
1643 #else
1644 static unsigned int kerSysDyingGaspIsr(void)
1645 #endif
1646 {       
1647     struct list_head *pos;
1648     CB_DGASP_LIST *tmp, *dsl = NULL;    
1649
1650     if (kerSysDyingGaspCheckPowerLoss()) {        
1651
1652         /* first to turn off everything other than dsl */        
1653         list_for_each(pos, &g_cb_dgasp_list_head->list) {       
1654             tmp = list_entry(pos, CB_DGASP_LIST, list);
1655             if(strncmp(tmp->name, "dsl", 3)) {
1656                 (tmp->cb_dgasp_fn)(tmp->context); 
1657             }else {
1658                 dsl = tmp;                      
1659             }       
1660         }  
1661         
1662         /* now send dgasp */
1663         if(dsl)
1664             (dsl->cb_dgasp_fn)(dsl->context); 
1665
1666         /* reset and shutdown system */
1667         kerSysDyingGaspShutdown();
1668     }
1669 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
1670 return( IRQ_HANDLED );
1671 #else
1672     return( 1 );
1673 #endif
1674 }
1675
1676 static void __init kerSysInitDyingGaspHandler( void )
1677 {
1678     CB_DGASP_LIST *new_node;
1679
1680     if( g_cb_dgasp_list_head != NULL) {
1681         printk("Error: kerSysInitDyingGaspHandler: list head is not null\n");
1682         return; 
1683     }
1684     new_node= (CB_DGASP_LIST *)kmalloc(sizeof(CB_DGASP_LIST), GFP_KERNEL);
1685     memset(new_node, 0x00, sizeof(CB_DGASP_LIST));
1686     INIT_LIST_HEAD(&new_node->list);    
1687     g_cb_dgasp_list_head = new_node; 
1688                 
1689 } /* kerSysInitDyingGaspHandler */
1690
1691 static void __exit kerSysDeinitDyingGaspHandler( void )
1692 {
1693     struct list_head *pos;
1694     CB_DGASP_LIST *tmp; 
1695         
1696     if(g_cb_dgasp_list_head == NULL)
1697         return;
1698         
1699     list_for_each(pos, &g_cb_dgasp_list_head->list) {           
1700         tmp = list_entry(pos, CB_DGASP_LIST, list);
1701         list_del(pos);
1702         kfree(tmp);
1703     }       
1704
1705     kfree(g_cb_dgasp_list_head);        
1706     g_cb_dgasp_list_head = NULL;
1707     
1708 } /* kerSysDeinitDyingGaspHandler */
1709
1710 void kerSysRegisterDyingGaspHandler(char *devname, void *cbfn, void *context)
1711 {
1712     CB_DGASP_LIST *new_node;
1713
1714     if( g_cb_dgasp_list_head == NULL) {
1715         printk("Error: kerSysRegisterDyingGaspHandler: list head is null\n");   
1716         return;    
1717     }
1718     
1719     if( devname == NULL || cbfn == NULL ) {
1720         printk("Error: kerSysRegisterDyingGaspHandler: register info not enough (%s,%x,%x)\n", devname, (unsigned int)cbfn, (unsigned int)context);             
1721         return;
1722     }
1723        
1724     new_node= (CB_DGASP_LIST *)kmalloc(sizeof(CB_DGASP_LIST), GFP_KERNEL);
1725     memset(new_node, 0x00, sizeof(CB_DGASP_LIST));    
1726     INIT_LIST_HEAD(&new_node->list);
1727     strncpy(new_node->name, devname, IFNAMSIZ);
1728     new_node->cb_dgasp_fn = (cb_dgasp_t)cbfn;
1729     new_node->context = context;
1730     list_add(&new_node->list, &g_cb_dgasp_list_head->list);
1731     
1732     printk("dgasp: kerSysRegisterDyingGaspHandler: %s registered \n", devname);
1733                 
1734 } /* kerSysRegisterDyingGaspHandler */
1735
1736 void kerSysDeregisterDyingGaspHandler(char *devname)
1737 {
1738     struct list_head *pos;
1739     CB_DGASP_LIST *tmp;    
1740     
1741     if(g_cb_dgasp_list_head == NULL) {
1742         printk("Error: kerSysDeregisterDyingGaspHandler: list head is null\n");
1743         return; 
1744     }
1745
1746     if(devname == NULL) {
1747         printk("Error: kerSysDeregisterDyingGaspHandler: devname is null\n");
1748         return; 
1749     }
1750     
1751     printk("kerSysDeregisterDyingGaspHandler: %s is deregistering\n", devname);
1752
1753     list_for_each(pos, &g_cb_dgasp_list_head->list) {           
1754         tmp = list_entry(pos, CB_DGASP_LIST, list);
1755         if(!strcmp(tmp->name, devname)) {
1756             list_del(pos);
1757             kfree(tmp);
1758             printk("kerSysDeregisterDyingGaspHandler: %s is deregistered\n", devname);
1759             return;
1760         }
1761     }   
1762     printk("kerSysDeregisterDyingGaspHandler: %s not (de)registered\n", devname);
1763         
1764 } /* kerSysDeregisterDyingGaspHandler */
1765
1766 /***************************************************************************
1767  * MACRO to call driver initialization and cleanup functions.
1768  ***************************************************************************/
1769 module_init( brcm_board_init );
1770 module_exit( brcm_board_cleanup );
1771
1772 EXPORT_SYMBOL(kerSysNvRamGet);
1773 EXPORT_SYMBOL(dumpaddr);
1774 EXPORT_SYMBOL(kerSysGetMacAddress);
1775 EXPORT_SYMBOL(kerSysReleaseMacAddress);
1776 EXPORT_SYMBOL(kerSysGetSdramSize);
1777 EXPORT_SYMBOL(kerSysLedCtrl);
1778 EXPORT_SYMBOL(kerSysLedRegisterHwHandler);
1779 EXPORT_SYMBOL(BpGetBoardIds);
1780 EXPORT_SYMBOL(BpGetSdramSize);
1781 EXPORT_SYMBOL(BpGetPsiSize);
1782 EXPORT_SYMBOL(BpGetEthernetMacInfo);
1783 EXPORT_SYMBOL(BpGetRj11InnerOuterPairGpios);
1784 EXPORT_SYMBOL(BpGetPressAndHoldResetGpio);
1785 EXPORT_SYMBOL(BpGetVoipResetGpio);
1786 EXPORT_SYMBOL(BpGetVoipIntrGpio);
1787 EXPORT_SYMBOL(BpGetPcmciaResetGpio);
1788 EXPORT_SYMBOL(BpGetRtsCtsUartGpios);
1789 EXPORT_SYMBOL(BpGetAdslLedGpio);
1790 EXPORT_SYMBOL(BpGetAdslFailLedGpio);
1791 EXPORT_SYMBOL(BpGetWirelessLedGpio);
1792 EXPORT_SYMBOL(BpGetUsbLedGpio);
1793 EXPORT_SYMBOL(BpGetHpnaLedGpio);
1794 EXPORT_SYMBOL(BpGetWanDataLedGpio);
1795 EXPORT_SYMBOL(BpGetPppLedGpio);
1796 EXPORT_SYMBOL(BpGetPppFailLedGpio);
1797 EXPORT_SYMBOL(BpGetVoipLedGpio);
1798 EXPORT_SYMBOL(BpGetWirelessExtIntr);
1799 EXPORT_SYMBOL(BpGetAdslDyingGaspExtIntr);
1800 EXPORT_SYMBOL(BpGetVoipExtIntr);
1801 EXPORT_SYMBOL(BpGetHpnaExtIntr);
1802 EXPORT_SYMBOL(BpGetHpnaChipSelect);
1803 EXPORT_SYMBOL(BpGetVoipChipSelect);
1804 EXPORT_SYMBOL(BpGetWirelessSesBtnGpio);
1805 EXPORT_SYMBOL(BpGetWirelessSesExtIntr);
1806 EXPORT_SYMBOL(BpGetWirelessSesLedGpio);
1807 EXPORT_SYMBOL(kerSysRegisterDyingGaspHandler);
1808 EXPORT_SYMBOL(kerSysDeregisterDyingGaspHandler);
1809 EXPORT_SYMBOL(kerSysGetCycleCount);
1810 EXPORT_SYMBOL(kerSysSetWdTimer);
1811 EXPORT_SYMBOL(kerSysWakeupMonitorTask);
1812