www.usr.com/support/gpl/USR9113_release1.0.tar.gz
[bcm963xx.git] / bcmdrivers / opensource / char / board / bcm963xx / impl1 / board.c
index 3de06a4..36290ad 100755 (executable)
  *              for the board related ioctl calls: flash, get free kernel
  *              page and dump kernel memory, etc.
  *
- * Created on :  2/20/2002  seanl:  use cfiflash.c, cfliflash.h (AMD specific)
  *
  ***************************************************************************/
 
-
 /* Includes. */
+#include <linux/version.h>
 #include <linux/init.h>
 #include <linux/fs.h>
 #include <linux/interrupt.h>
 #include <linux/wait.h>
 #include <linux/poll.h>
 #include <linux/sched.h>
+#include <linux/list.h>
+#include <linux/if.h>
 
 #include <bcm_map_part.h>
 #include <board.h>
 #include <bcmTag.h>
 #include "boardparms.h"
-#include "cfiflash.h"
+#include "flash_api.h"
 #include "bcm_intr.h"
 #include "board.h"
+#include "bcm_map_part.h"
 
 /* Typedefs. */
-#if defined (NON_CONSECUTIVE_MAC)
-// used to be the last octet. Now changed to the first 5 bits of the the forth octet
-// to reduced the duplicated MAC addresses.
-#define CHANGED_OCTET   3
-#define SHIFT_BITS      3
-#else
-#define CHANGED_OCTET   1
-#define SHIFT_BITS      0
-#endif
 
 #if defined (WIRELESS)
 #define SES_BTN_PRESSED 0x00000001
@@ -81,7 +74,7 @@ typedef struct
     unsigned long ulSdramSize;
     unsigned long ulPsiSize;
     unsigned long ulNumMacAddrs;
-    unsigned long ucaBaseMacAddr[NVRAM_MAC_ADDRESS_LEN];
+    unsigned char ucaBaseMacAddr[NVRAM_MAC_ADDRESS_LEN];
     char chCountry[4]; // USR9108
     MAC_ADDR_INFO MacAddrs[1];
 } NVRAM_INFO, *PNVRAM_INFO;
@@ -92,20 +85,33 @@ typedef struct
 } BOARD_IOC, *PBOARD_IOC;
 
 
+/*Dyinggasp callback*/
+typedef void (*cb_dgasp_t)(void *arg);
+typedef struct _CB_DGASP__LIST
+{
+    struct list_head list;
+    char name[IFNAMSIZ];
+    cb_dgasp_t cb_dgasp_fn;
+    void *context;
+}CB_DGASP_LIST , *PCB_DGASP_LIST;
+
+
 static LED_MAP_PAIR LedMapping[] =
 {   // led name     Initial state       physical pin (ledMask)
-    {kLedEnd,       kLedStateOff,       0, 0, 0, 0},
-    {kLedEnd,       kLedStateOff,       0, 0, 0, 0},
-    {kLedEnd,       kLedStateOff,       0, 0, 0, 0},
-    {kLedEnd,       kLedStateOff,       0, 0, 0, 0},
-    {kLedEnd,       kLedStateOff,       0, 0, 0, 0},
-    {kLedEnd,       kLedStateOff,       0, 0, 0, 0}, 
-    {kLedEnd,       kLedStateOff,       0, 0, 0, 0}, 
-    {kLedEnd,       kLedStateOff,       0, 0, 0, 0},     
-    {kLedEnd,       kLedStateOff,       0, 0, 0, 0} // NOTE: kLedEnd has to be at the end.
+    {kLedEnd,       kLedStateOff,       0, 0, 0, 0, 0, 0},
+    {kLedEnd,       kLedStateOff,       0, 0, 0, 0, 0, 0},
+    {kLedEnd,       kLedStateOff,       0, 0, 0, 0, 0, 0},
+    {kLedEnd,       kLedStateOff,       0, 0, 0, 0, 0, 0},
+    {kLedEnd,       kLedStateOff,       0, 0, 0, 0, 0, 0},
+    {kLedEnd,       kLedStateOff,       0, 0, 0, 0, 0, 0},
+    {kLedEnd,       kLedStateOff,       0, 0, 0, 0, 0, 0},
+    {kLedEnd,       kLedStateOff,       0, 0, 0, 0, 0, 0},   
+    {kLedEnd,       kLedStateOff,       0, 0, 0, 0, 0, 0},   
+    {kLedEnd,       kLedStateOff,       0, 0, 0, 0, 0, 0} // NOTE: kLedEnd has to be at the end.
 };
 
 /* Externs. */
+extern struct file fastcall *fget_light(unsigned int fd, int *fput_needed);
 extern unsigned int nr_free_pages (void);
 extern const char *get_system_type(void);
 extern void kerSysFlashInit(void);
@@ -116,6 +122,7 @@ extern void __init boardLedInit(PLED_MAP_PAIR);
 extern void boardLedCtrl(BOARD_LED_NAME, BOARD_LED_STATE);
 extern void kerSysLedRegisterHandler( BOARD_LED_NAME ledName,
     HANDLE_LED_FUNC ledHwFunc, int ledFailType );
+extern UINT32 getCrc32(byte *pdata, UINT32 size, UINT32 crc);
 
 /* Prototypes. */
 void __init InitNvramInfo( void );
@@ -128,6 +135,21 @@ static int board_release(struct inode *inode, struct file *filp);
 static BOARD_IOC* borad_ioc_alloc(void);
 static void borad_ioc_free(BOARD_IOC* board_ioc);
 
+/* DyingGasp function prototype */
+static void __init kerSysDyingGaspMapIntr(void);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+static irqreturn_t kerSysDyingGaspIsr(int irq, void * dev_id, struct pt_regs * regs);
+#else
+static unsigned int kerSysDyingGaspIsr(void);
+#endif
+static void __init kerSysInitDyingGaspHandler( void );
+static void __exit kerSysDeinitDyingGaspHandler( void );
+/* -DyingGasp function prototype - */
+
+static int ConfigCs(BOARD_IOCTL_PARMS *parms);
+static void SetPll(int pll_mask, int pll_value);
+static void SetGpio(int gpio, GPIO_STATE_t state);
+
 #if defined (WIRELESS)
 static irqreturn_t sesBtn_isr(int irq, void *dev_id, struct pt_regs *ptregs);
 static void __init sesBtn_mapGpio(void);
@@ -140,9 +162,18 @@ static void __init ses_board_init(void);
 static void __exit ses_board_deinit(void);
 #endif
 
+static irqreturn_t reset_isr(int irq, void *dev_id, struct pt_regs *ptregs);
+
 static PNVRAM_INFO g_pNvramInfo = NULL;
 static int g_ledInitialized = 0;
 static wait_queue_head_t g_board_wait_queue;
+static CB_DGASP_LIST *g_cb_dgasp_list_head = NULL;
+
+static int g_wakeup_monitor = 0;
+static struct file *g_monitor_file = NULL;
+static struct task_struct *g_monitor_task = NULL;
+static unsigned int (*g_orig_fop_poll)
+    (struct file *, struct poll_table_struct *) = NULL;
 
 static struct file_operations board_fops =
 {
@@ -198,6 +229,7 @@ static int __init brcm_board_init( void )
      {kLedEnd, NULL, NULL}
     };
 
+    unsigned short pah_irq;    
     int ret;
         
     ret = register_chrdev(BOARD_DRV_MAJOR, "bcrmboard", &board_fops );
@@ -208,6 +240,7 @@ static int __init brcm_board_init( void )
         PLED_MAP_PAIR pLedMap = LedMapping;
         unsigned short gpio;
         struct BpLedInformation *pInfo;
+        ETHERNET_MAC_INFO EnetInfo;
 
         printk("brcmboard: brcm_board_init entry\n");
         board_major = BOARD_DRV_MAJOR;
@@ -215,28 +248,56 @@ static int __init brcm_board_init( void )
 
         for( pInfo = bpLedInfo; pInfo->ledName != kLedEnd; pInfo++ )
         {
-            if( pInfo->bpFunc && (*pInfo->bpFunc) (&gpio) == BP_SUCCESS )
+            if( pInfo->bpFunc && (*pInfo->bpFunc) (&gpio) == BP_SUCCESS &&
+                gpio != BP_HW_DEFINED_AH && gpio != BP_HW_DEFINED_AL )
             {
                 pLedMap->ledName = pInfo->ledName;
                 pLedMap->ledMask = GPIO_NUM_TO_MASK(gpio);
                 pLedMap->ledActiveLow = (gpio & BP_ACTIVE_LOW) ? 1 : 0;
+                pLedMap->ledSerial = (gpio & BP_GPIO_SERIAL) ? 1 : 0;
             }
-            if( pInfo->bpFuncFail && (*pInfo->bpFuncFail) (&gpio) == BP_SUCCESS )
+            if( pInfo->bpFuncFail && (*pInfo->bpFuncFail)(&gpio)==BP_SUCCESS &&
+                gpio != BP_HW_DEFINED_AH && gpio != BP_HW_DEFINED_AL )
             {
                 pLedMap->ledName = pInfo->ledName;
                 pLedMap->ledMaskFail = GPIO_NUM_TO_MASK(gpio);
                 pLedMap->ledActiveLowFail = (gpio & BP_ACTIVE_LOW) ? 1 : 0;
+                pLedMap->ledSerialFail = (gpio & BP_GPIO_SERIAL) ? 1 : 0;
             }
             if( pLedMap->ledName != kLedEnd )
                 pLedMap++;
         }
+
+        if( BpGetEthernetMacInfo( &EnetInfo, 1 ) == BP_SUCCESS )
+        {
+            if( EnetInfo.usGpioPhyLinkSpeed != BP_NOT_DEFINED )
+            {
+                /* The internal Ethernet PHY has a GPIO for 10/100 link speed. */
+                gpio = EnetInfo.usGpioPhyLinkSpeed;
+                pLedMap->ledName = kLedEphyLinkSpeed;
+                pLedMap->ledMask = GPIO_NUM_TO_MASK(gpio);
+                pLedMap->ledActiveLow = (gpio & BP_ACTIVE_LOW) ? 1 : 0;
+                pLedMap->ledSerial = (gpio & BP_GPIO_SERIAL) ? 1 : 0;
+                pLedMap++;
+            }
+        }
         
         init_waitqueue_head(&g_board_wait_queue);
 #if defined (WIRELESS)
         ses_board_init();
 #endif        
+        kerSysInitDyingGaspHandler();
+        kerSysDyingGaspMapIntr();
+
         boardLedInit(LedMapping);
         g_ledInitialized = 1;
+
+        if( BpGetPressAndHoldResetExtIntr(&pah_irq) == BP_SUCCESS )
+        {
+            pah_irq += INTERRUPT_ID_EXTERNAL_0;        
+            BcmHalMapInterrupt((FN_HANDLER)reset_isr, 0, pah_irq);
+            BcmHalInterruptEnable(pah_irq);
+        }
     }
 
     return ret;
@@ -278,12 +339,13 @@ void __init InitNvramInfo( void )
 void __exit brcm_board_cleanup( void )
 {
     printk("brcm_board_cleanup()\n");
-
+       
     if (board_major != -1) 
     {
 #if defined (WIRELESS)         
        ses_board_deinit();
 #endif         
+        kerSysDeinitDyingGaspHandler();
         unregister_chrdev(board_major, "board_ioctl");
     }
 } 
@@ -332,7 +394,9 @@ static int board_release(struct inode *inode, struct file *filp)
 static unsigned int board_poll(struct file *filp, struct poll_table_struct *wait)
 {
     unsigned int mask = 0;
+#if defined (WIRELESS)         
     BOARD_IOC *board_ioc = filp->private_data;         
+#endif
        
     poll_wait(filp, &g_board_wait_queue, wait);
 #if defined (WIRELESS)         
@@ -340,14 +404,15 @@ static unsigned int board_poll(struct file *filp, struct poll_table_struct *wait
         mask |= sesBtn_poll(filp, wait);
     }                  
 #endif    
+
     return mask;
 }
 
 
 static ssize_t board_read(struct file *filp,  char __user *buffer, size_t count, loff_t *ppos)
 {
-    BOARD_IOC *board_ioc = filp->private_data;
 #if defined (WIRELESS)    
+    BOARD_IOC *board_ioc = filp->private_data;
     if(board_ioc->eventmask & SES_EVENTS){
        return sesBtn_read(filp, buffer, count, ppos);
     }
@@ -438,11 +503,18 @@ void kerSysMipsSoftReset(void)
 
 int kerSysGetMacAddress( unsigned char *pucaMacAddr, unsigned long ulId )
 {
+    const unsigned long constMacAddrIncIndex = 3;
     int nRet = 0;
     PMAC_ADDR_INFO pMai = NULL;
     PMAC_ADDR_INFO pMaiFreeNoId = NULL;
     PMAC_ADDR_INFO pMaiFreeId = NULL;
-    unsigned long i = 0, ulIdxNoId = 0, ulIdxId = 0, shiftedIdx = 0;
+    unsigned long i = 0, ulIdxNoId = 0, ulIdxId = 0, baseMacAddr = 0;
+
+    /* baseMacAddr = last 3 bytes of the base MAC address treated as a 24 bit integer */
+    memcpy((unsigned char *) &baseMacAddr,
+        &g_pNvramInfo->ucaBaseMacAddr[constMacAddrIncIndex],
+        NVRAM_MAC_ADDRESS_LEN - constMacAddrIncIndex);
+    baseMacAddr >>= 8;
 
     for( i = 0, pMai = g_pNvramInfo->MacAddrs; i < g_pNvramInfo->ulNumMacAddrs;
         i++, pMai++ )
@@ -450,10 +522,11 @@ int kerSysGetMacAddress( unsigned char *pucaMacAddr, unsigned long ulId )
         if( ulId == pMai->ulId || ulId == MAC_ADDRESS_ANY )
         {
             /* This MAC address has been used by the caller in the past. */
+            baseMacAddr = (baseMacAddr + i) << 8;
             memcpy( pucaMacAddr, g_pNvramInfo->ucaBaseMacAddr,
-                NVRAM_MAC_ADDRESS_LEN );
-            shiftedIdx = i;
-            pucaMacAddr[NVRAM_MAC_ADDRESS_LEN - CHANGED_OCTET] += (shiftedIdx << SHIFT_BITS);
+                constMacAddrIncIndex);
+            memcpy( pucaMacAddr + constMacAddrIncIndex, (unsigned char *)
+                &baseMacAddr, NVRAM_MAC_ADDRESS_LEN - constMacAddrIncIndex );
             pMai->chInUse = 1;
             pMaiFreeNoId = pMaiFreeId = NULL;
             break;
@@ -488,15 +561,21 @@ int kerSysGetMacAddress( unsigned char *pucaMacAddr, unsigned long ulId )
         memcpy(pucaMacAddr, g_pNvramInfo->ucaBaseMacAddr,NVRAM_MAC_ADDRESS_LEN);
         if( pMaiFreeNoId )
         {
-            shiftedIdx = ulIdxNoId;
-            pucaMacAddr[NVRAM_MAC_ADDRESS_LEN - CHANGED_OCTET] += (shiftedIdx << SHIFT_BITS);
+            baseMacAddr = (baseMacAddr + ulIdxNoId) << 8;
+            memcpy( pucaMacAddr, g_pNvramInfo->ucaBaseMacAddr,
+                constMacAddrIncIndex);
+            memcpy( pucaMacAddr + constMacAddrIncIndex, (unsigned char *)
+                &baseMacAddr, NVRAM_MAC_ADDRESS_LEN - constMacAddrIncIndex );
             pMaiFreeNoId->ulId = ulId;
             pMaiFreeNoId->chInUse = 1;
         }
         else
         {
-            shiftedIdx = ulIdxId;
-            pucaMacAddr[NVRAM_MAC_ADDRESS_LEN - CHANGED_OCTET] += (shiftedIdx << SHIFT_BITS);
+            baseMacAddr = (baseMacAddr + ulIdxId) << 8;
+            memcpy( pucaMacAddr, g_pNvramInfo->ucaBaseMacAddr,
+                constMacAddrIncIndex);
+            memcpy( pucaMacAddr + constMacAddrIncIndex, (unsigned char *)
+                &baseMacAddr, NVRAM_MAC_ADDRESS_LEN - constMacAddrIncIndex );
             pMaiFreeId->ulId = ulId;
             pMaiFreeId->chInUse = 1;
         }
@@ -510,15 +589,24 @@ int kerSysGetMacAddress( unsigned char *pucaMacAddr, unsigned long ulId )
 
 int kerSysReleaseMacAddress( unsigned char *pucaMacAddr )
 {
+    const unsigned long constMacAddrIncIndex = 3;
     int nRet = -EINVAL;
     unsigned long ulIdx = 0;
-    int idx = (pucaMacAddr[NVRAM_MAC_ADDRESS_LEN - CHANGED_OCTET] -
-        g_pNvramInfo->ucaBaseMacAddr[NVRAM_MAC_ADDRESS_LEN - CHANGED_OCTET]);
+    unsigned long baseMacAddr = 0;
+    unsigned long relMacAddr = 0;
+
+    /* baseMacAddr = last 3 bytes of the base MAC address treated as a 24 bit integer */
+    memcpy((unsigned char *) &baseMacAddr,
+        &g_pNvramInfo->ucaBaseMacAddr[constMacAddrIncIndex],
+        NVRAM_MAC_ADDRESS_LEN - constMacAddrIncIndex);
+    baseMacAddr >>= 8;
 
-    // if overflow 255 (negitive), add 256 to have the correct index
-    if (idx < 0)
-        idx += 256;
-    ulIdx = (unsigned long) (idx >> SHIFT_BITS);
+    /* Get last 3 bytes of MAC address to release. */
+    memcpy((unsigned char *) &relMacAddr, &pucaMacAddr[constMacAddrIncIndex],
+        NVRAM_MAC_ADDRESS_LEN - constMacAddrIncIndex);
+    relMacAddr >>= 8;
+
+    ulIdx = relMacAddr - baseMacAddr;
 
     if( ulIdx < g_pNvramInfo->ulNumMacAddrs )
     {
@@ -533,6 +621,27 @@ int kerSysReleaseMacAddress( unsigned char *pucaMacAddr )
     return( nRet );
 } /* kerSysReleaseMacAddr */
 
+// USR9109/91113
+void kerSysSetMacAddress(unsigned char *pucaMacAddr)
+{
+    UINT32 crc = CRC32_INIT_VALUE;
+    NVRAM_DATA NvramData;
+    volatile unsigned char *mac;
+                                                                                
+    memcpy((char *)&NvramData, (char *)get_nvram_start_addr(), sizeof(NVRAM_DATA));
+                                                                                
+    mac = (unsigned char*)NvramData.ucaBaseMacAddr;
+    printk("Original ucaBaseMacAddr: %02X %02X %02X %02X %02X %02X\r\n", mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
+                                                                                
+    memcpy(NvramData.ucaBaseMacAddr, pucaMacAddr, NVRAM_MAC_ADDRESS_LEN);
+    printk("New Mac: %02X %02X %02X %02X %02X %02X\r\n",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
+                                                                                
+    NvramData.ulCheckSum = 0;
+    NvramData.ulCheckSum = getCrc32((char *)&NvramData, (UINT32) sizeof(NVRAM_DATA), crc);
+    kerSysNvRamSet((char *)&NvramData, sizeof(NVRAM_DATA), NVRAM_VERSION_NUMBER_ADDRESS);
+
+} /* kerSysSetMacAddr */
+
 int kerSysGetSdramSize( void )
 {
     return( (int) g_pNvramInfo->ulSdramSize );
@@ -545,6 +654,240 @@ void kerSysLedCtrl(BOARD_LED_NAME ledName, BOARD_LED_STATE ledState)
       boardLedCtrl(ledName, ledState);
 }
 
+unsigned int kerSysMonitorPollHook( struct file *f, struct poll_table_struct *t)
+{
+    int mask = (*g_orig_fop_poll) (f, t);
+
+    if( g_wakeup_monitor == 1 && g_monitor_file == f )
+    {
+        /* If g_wakeup_monitor is non-0, the user mode application needs to
+         * return from a blocking select function.  Return POLLPRI which will
+         * cause the select to return with the exception descriptor set.
+         */
+        mask |= POLLPRI;
+        g_wakeup_monitor = 0;
+    }
+
+    return( mask );
+}
+
+/* Put the user mode application that monitors link state on a run queue. */
+void kerSysWakeupMonitorTask( void )
+{
+    g_wakeup_monitor = 1;
+    if( g_monitor_task )
+        wake_up_process( g_monitor_task );
+}
+
+static PFILE_TAG getTagFromPartition(int imageNumber)
+{
+    static unsigned char sectAddr1[sizeof(FILE_TAG)];
+    static unsigned char sectAddr2[sizeof(FILE_TAG)];
+    int blk = 0;
+    UINT32 crc;
+    PFILE_TAG pTag = NULL;
+    unsigned char *pBase = flash_get_memptr(0);
+    unsigned char *pSectAddr = NULL;
+
+    /* The image tag for the first image is always after the boot loader.
+     * The image tag for the second image, if it exists, is at one half
+     * of the flash size.
+     */
+    if( imageNumber == 1 )
+    {
+        blk = flash_get_blk((int) (pBase + FLASH_LENGTH_BOOT_ROM));
+        pSectAddr = sectAddr1;
+    }
+    else
+        if( imageNumber == 2 )
+        {
+            blk = flash_get_blk((int) (pBase + (flash_get_total_size() / 2)));
+            pSectAddr = sectAddr2;
+        }
+
+    if( blk )
+    {
+        memset(pSectAddr, 0x00, sizeof(FILE_TAG));
+        flash_read_buf((unsigned short) blk, 0, pSectAddr, sizeof(FILE_TAG));
+        crc = CRC32_INIT_VALUE;
+        crc = getCrc32(pSectAddr, (UINT32)TAG_LEN-TOKEN_LEN, crc);      
+        pTag = (PFILE_TAG) pSectAddr;
+        if (crc != (UINT32)(*(UINT32*)(pTag->tagValidationToken)))
+            pTag = NULL;
+    }
+
+    return( pTag );
+}
+
+static int getPartitionFromTag( PFILE_TAG pTag )
+{
+    int ret = 0;
+
+    if( pTag )
+    {
+        PFILE_TAG pTag1 = getTagFromPartition(1);
+        PFILE_TAG pTag2 = getTagFromPartition(2);
+        int sequence = simple_strtoul(pTag->imageSequence,  NULL, 10);
+        int sequence1 = (pTag1) ? simple_strtoul(pTag1->imageSequence, NULL, 10)
+            : -1;
+        int sequence2 = (pTag2) ? simple_strtoul(pTag2->imageSequence, NULL, 10)
+            : -1;
+
+        if( pTag1 && sequence == sequence1 )
+            ret = 1;
+        else
+            if( pTag2 && sequence == sequence2 )
+                ret = 2;
+    }
+
+    return( ret );
+}
+
+static PFILE_TAG getBootImageTag(void)
+{
+    PFILE_TAG pTag = NULL;
+    PFILE_TAG pTag1 = getTagFromPartition(1);
+    PFILE_TAG pTag2 = getTagFromPartition(2);
+
+    if( pTag1 && pTag2 )
+    {
+        /* Two images are flashed. */
+        int sequence1 = simple_strtoul(pTag1->imageSequence, NULL, 10);
+        int sequence2 = simple_strtoul(pTag2->imageSequence, NULL, 10);
+        char *p;
+        char bootPartition = BOOT_LATEST_IMAGE;
+        NVRAM_DATA nvramData;
+
+        memcpy((char *) &nvramData, (char *) get_nvram_start_addr(),
+            sizeof(nvramData));
+        for( p = nvramData.szBootline; p[2] != '\0'; p++ )
+            if( p[0] == 'p' && p[1] == '=' )
+            {
+                bootPartition = p[2];
+                break;
+            }
+
+        if( bootPartition == BOOT_LATEST_IMAGE )
+            pTag = (sequence2 > sequence1) ? pTag2 : pTag1;
+        else /* Boot from the image configured. */
+            pTag = (sequence2 < sequence1) ? pTag2 : pTag1;
+    }
+    else
+        /* One image is flashed. */
+        pTag = (pTag2) ? pTag2 : pTag1;
+
+    return( pTag );
+}
+
+static void UpdateImageSequenceNumber( unsigned char *imageSequence )
+{
+    int newImageSequence = 0;
+    PFILE_TAG pTag = getTagFromPartition(1);
+
+    if( pTag )
+        newImageSequence = simple_strtoul(pTag->imageSequence, NULL, 10);
+
+    pTag = getTagFromPartition(2);
+    if(pTag && simple_strtoul(pTag->imageSequence, NULL, 10) > newImageSequence)
+        newImageSequence = simple_strtoul(pTag->imageSequence, NULL, 10);
+
+    newImageSequence++;
+    sprintf(imageSequence, "%d", newImageSequence);
+}
+
+static int flashFsKernelImage( int destAddr, unsigned char *imagePtr,
+    int imageLen )
+{
+    int status = 0;
+    PFILE_TAG pTag = (PFILE_TAG) imagePtr;
+    int rootfsAddr = simple_strtoul(pTag->rootfsAddress, NULL, 10) + BOOT_OFFSET;
+    int kernelAddr = simple_strtoul(pTag->kernelAddress, NULL, 10) + BOOT_OFFSET;
+    char *p;
+    char *tagFs = imagePtr;
+    unsigned int baseAddr = (unsigned int) flash_get_memptr(0);
+    unsigned int totalSize = (unsigned int) flash_get_total_size();
+    unsigned int availableSizeOneImg = totalSize -
+        ((unsigned int) rootfsAddr - baseAddr) - FLASH_RESERVED_AT_END;
+    unsigned int reserveForTwoImages =
+        (FLASH_LENGTH_BOOT_ROM > FLASH_RESERVED_AT_END)
+        ? FLASH_LENGTH_BOOT_ROM : FLASH_RESERVED_AT_END;
+    unsigned int availableSizeTwoImgs =
+        (totalSize / 2) - reserveForTwoImages;
+    unsigned int newImgSize = simple_strtoul(pTag->rootfsLen, NULL, 10) +
+        simple_strtoul(pTag->kernelLen, NULL, 10);
+    PFILE_TAG pCurTag = getBootImageTag();
+    UINT32 crc = CRC32_INIT_VALUE;
+    unsigned int curImgSize = 0;
+    NVRAM_DATA nvramData;
+
+    memcpy((char *)&nvramData, (char *)get_nvram_start_addr(),sizeof(nvramData));
+
+    if( pCurTag )
+    {
+        curImgSize = simple_strtoul(pCurTag->rootfsLen, NULL, 10) +
+            simple_strtoul(pCurTag->kernelLen, NULL, 10);
+    }
+
+    if( newImgSize > availableSizeOneImg)
+    {
+        printk("Illegal image size %d.  Image size must not be greater "
+            "than %d.\n", newImgSize, availableSizeOneImg);
+        return -1;
+    }
+
+    // If the current image fits in half the flash space and the new
+    // image to flash also fits in half the flash space, then flash it
+    // in the partition that is not currently being used to boot from.
+    if( curImgSize <= availableSizeTwoImgs &&
+        newImgSize <= availableSizeTwoImgs &&
+        getPartitionFromTag( pCurTag ) == 1 )
+    {
+        // Update rootfsAddr to point to the second boot partition.
+        int offset = (totalSize / 2) + TAG_LEN;
+
+        sprintf(((PFILE_TAG) tagFs)->kernelAddress, "%lu",
+            (unsigned long) IMAGE_BASE + offset + (kernelAddr - rootfsAddr));
+        kernelAddr = baseAddr + offset + (kernelAddr - rootfsAddr);
+
+        sprintf(((PFILE_TAG) tagFs)->rootfsAddress, "%lu",
+            (unsigned long) IMAGE_BASE + offset);
+        rootfsAddr = baseAddr + offset;
+    }
+
+    UpdateImageSequenceNumber( ((PFILE_TAG) tagFs)->imageSequence );
+    crc = getCrc32((unsigned char *)tagFs, (UINT32)TAG_LEN-TOKEN_LEN, crc);      
+    *(unsigned long *) &((PFILE_TAG) tagFs)->tagValidationToken[0] = crc;
+
+    if( (status = kerSysBcmImageSet((rootfsAddr-TAG_LEN), tagFs,
+        TAG_LEN + newImgSize)) != 0 )
+    {
+        printk("Failed to flash root file system. Error: %d\n", status);
+        return status;
+    }
+
+    for( p = nvramData.szBootline; p[2] != '\0'; p++ )
+        if( p[0] == 'p' && p[1] == '=' && p[2] != BOOT_LATEST_IMAGE )
+        {
+            UINT32 crc = CRC32_INIT_VALUE;
+    
+            // Change boot partition to boot from new image.
+            p[2] = BOOT_LATEST_IMAGE;
+
+            nvramData.ulCheckSum = 0;
+            crc = getCrc32((char *)&nvramData, (UINT32) sizeof(NVRAM_DATA), crc);      
+            nvramData.ulCheckSum = crc;
+            kerSysNvRamSet( (char *) &nvramData, sizeof(nvramData), 0);
+            break;
+        }
+
+    return(status);
+}
+
+PFILE_TAG kerSysImageTagGet(void)
+{
+    return( getBootImageTag() );
+}
+
 
 //********************************************************************************************
 // misc. ioctl calls come to here. (flash, led, reset, kernel memory access, etc.)
@@ -555,7 +898,6 @@ static int board_ioctl( struct inode *inode, struct file *flip,
     int ret = 0;
     BOARD_IOCTL_PARMS ctrlParms;
     unsigned char ucaMacAddr[NVRAM_MAC_ADDRESS_LEN];
-    int allowedSize;
 
     switch (command) 
     {
@@ -563,7 +905,6 @@ static int board_ioctl( struct inode *inode, struct file *flip,
             // not used for now.  kerSysBcmImageInit();
             break;
 
-
         case BOARD_IOCTL_FLASH_WRITE:
             if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0)
             {
@@ -573,7 +914,10 @@ static int board_ioctl( struct inode *inode, struct file *flip,
                 switch (ctrlParms.action)
                 {
                     case SCRATCH_PAD:
-                        ret = kerSysScratchPadSet(ctrlParms.string, ctrlParms.buf, ctrlParms.offset);
+                        if (ctrlParms.offset == -1)
+                              ret =  kerSysScratchPadClearAll();
+                        else
+                              ret = kerSysScratchPadSet(ctrlParms.string, ctrlParms.buf, ctrlParms.offset);
                         break;
 
                     case PERSISTENT:
@@ -585,10 +929,10 @@ static int board_ioctl( struct inode *inode, struct file *flip,
                         break;
 
                     case BCM_IMAGE_CFE:
-                        if( ctrlParms.strLen <= 0 || ctrlParms.strLen > FLASH45_LENGTH_BOOT_ROM )
+                        if( ctrlParms.strLen <= 0 || ctrlParms.strLen > FLASH_LENGTH_BOOT_ROM )
                         {
                             printk("Illegal CFE size [%d]. Size allowed: [%d]\n",
-                                ctrlParms.strLen, FLASH45_LENGTH_BOOT_ROM);
+                                ctrlParms.strLen, FLASH_LENGTH_BOOT_ROM);
                             ret = -1;
                             break;
                         }
@@ -598,8 +942,10 @@ static int board_ioctl( struct inode *inode, struct file *flip,
 
                         // set memory type field
                         BpGetSdramSize( (unsigned long *) &ctrlParms.string[SDRAM_TYPE_ADDRESS_OFFSET] );
+                        // set thread number field
+                        BpGetCMTThread( (unsigned long *) &ctrlParms.string[THREAD_NUM_ADDRESS_OFFSET] );
 
-                        ret = kerSysBcmImageSet(ctrlParms.offset, ctrlParms.string, ctrlParms.strLen);
+                        ret = kerSysBcmImageSet(ctrlParms.offset + BOOT_OFFSET, ctrlParms.string, ctrlParms.strLen);
 
                         // if nvram is not valid, restore the current nvram settings
                         if( BpSetBoardId( pNvramData->szBoardId ) != BP_SUCCESS &&
@@ -610,17 +956,11 @@ static int board_ioctl( struct inode *inode, struct file *flip,
                         break;
                         
                     case BCM_IMAGE_FS:
-                        allowedSize = (int) flash_get_total_size() - \
-                            FLASH_RESERVED_AT_END - TAG_LEN - FLASH45_LENGTH_BOOT_ROM;
-                        if( ctrlParms.strLen <= 0 || ctrlParms.strLen > allowedSize)
+                        if( (ret = flashFsKernelImage( ctrlParms.offset,
+                            ctrlParms.string, ctrlParms.strLen)) == 0 )
                         {
-                            printk("Illegal root file system size [%d]. Size allowed: [%d]\n",
-                                ctrlParms.strLen,  allowedSize);
-                            ret = -1;
-                            break;
+                            kerSysMipsSoftReset();
                         }
-                        ret = kerSysBcmImageSet(ctrlParms.offset, ctrlParms.string, ctrlParms.strLen);
-                        kerSysMipsSoftReset();
                         break;
 
                     case BCM_IMAGE_KERNEL:  // not used for now.
@@ -636,6 +976,9 @@ static int board_ioctl( struct inode *inode, struct file *flip,
                         // save NVRAM data into a local structure
                         memcpy( &SaveNvramData, pNvramData, sizeof(NVRAM_DATA) );
 
+                        if (ctrlParms.offset == 0) {
+                            ctrlParms.offset = FLASH_BASE;
+                        }
                         ret = kerSysBcmImageSet(ctrlParms.offset, ctrlParms.string, ctrlParms.strLen);
 
                         // if nvram is not valid, restore the current nvram settings
@@ -834,7 +1177,7 @@ static int board_ioctl( struct inode *inode, struct file *flip,
             else
                 ret = -EFAULT;
             break;
-
+                                                                                
         case BOARD_IOCTL_GET_CHIP_ID:
             ctrlParms.result = (int) (PERF->RevID & 0xFFFF0000) >> 16;
             __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));
@@ -1023,6 +1366,71 @@ static int board_ioctl( struct inode *inode, struct file *flip,
                 ret = -EFAULT;
             break;
 
+        case BOARD_IOCTL_SET_MONITOR_FD:
+            if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) {
+                int fput_needed = 0;
+
+                g_monitor_file = fget_light( ctrlParms.offset, &fput_needed );
+                if( g_monitor_file ) {
+                    /* Hook this file descriptor's poll function in order to set
+                     * the exception descriptor when there is a change in link
+                     * state.
+                     */
+                    g_monitor_task = current;
+                    g_orig_fop_poll = g_monitor_file->f_op->poll;
+                    g_monitor_file->f_op->poll = kerSysMonitorPollHook;
+                }
+            }
+            break;
+
+        case BOARD_IOCTL_WAKEUP_MONITOR_TASK:
+            kerSysWakeupMonitorTask();
+            break;
+
+        case BOARD_IOCTL_GET_VCOPE_GPIO:
+            if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) {
+                ret = ((ctrlParms.result = BpGetVcopeGpio(ctrlParms.offset)) != BP_NOT_DEFINED) ? 0 : -EFAULT;
+                __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));
+            }
+            else {
+                ret = -EFAULT;  
+                ctrlParms.result = BP_NOT_DEFINED;
+            }
+
+            break;
+
+        case BOARD_IOCTL_SET_CS_PAR: 
+            if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) {
+                ret = ConfigCs(&ctrlParms);
+                __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));
+            } 
+            else {
+                ret = -EFAULT;  
+            }
+            break;
+
+        case BOARD_IOCTL_SET_PLL: 
+            if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) {
+                SetPll(ctrlParms.strLen, ctrlParms.offset);
+                __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));
+                ret = 0;
+            } 
+            else {
+                ret = -EFAULT;  
+            }
+            break;
+
+        case BOARD_IOCTL_SET_GPIO:
+            if (copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) {
+                SetGpio(ctrlParms.strLen, ctrlParms.offset);
+                __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));
+                ret = 0;
+            } 
+            else {
+                ret = -EFAULT;  
+            }
+            break;
+    
         default:
             ret = -EINVAL;
             ctrlParms.result = 0;
@@ -1041,26 +1449,18 @@ static int board_ioctl( struct inode *inode, struct file *flip,
 #if defined (WIRELESS) 
 static irqreturn_t sesBtn_isr(int irq, void *dev_id, struct pt_regs *ptregs)
 {   
-#if defined(_BCM96338_) || defined(CONFIG_BCM96338)
     unsigned long gpio_mask = GPIO_NUM_TO_MASK(sesBtn_gpio);
-    volatile unsigned long *gpio_reg = &GPIO->GPIOio;
-#endif
-#if defined(_BCM96345_) || defined(CONFIG_BCM96345)
-    unsigned short gpio_mask = GPIO_NUM_TO_MASK(sesBtn_gpio);
-    volatile unsigned short *gpio_reg = &GPIO->GPIOio;
-#endif
-#if defined(_BCM96348_) || defined (CONFIG_BCM96348)
-    unsigned long gpio_mask = GPIO_NUM_TO_MASK(sesBtn_gpio);
-    volatile unsigned long *gpio_reg = &GPIO->GPIOio;
+    volatile unsigned long *gpio_io_reg = &GPIO->GPIOio;
 
-    if( (sesBtn_gpio & ~BP_ACTIVE_MASK) >= 32 )
+#if !defined(CONFIG_BCM96338)
+    if( (sesBtn_gpio & BP_GPIO_NUM_MASK) >= 32 )
     {
         gpio_mask = GPIO_NUM_TO_MASK_HIGH(sesBtn_gpio);
-        gpio_reg = &GPIO->GPIOio_high;
+        gpio_io_reg = &GPIO->GPIOio_high;
     }
 #endif 
                
-    if (!(*gpio_reg & gpio_mask)){
+    if (!(*gpio_io_reg & gpio_mask)){
         wake_up_interruptible(&g_board_wait_queue);
         return IRQ_RETVAL(1);
     } else {
@@ -1096,27 +1496,19 @@ static void __init sesBtn_mapIntr(int context)
 
 static unsigned int sesBtn_poll(struct file *file, struct poll_table_struct *wait)
 {
-#if defined(_BCM96338_) || defined(CONFIG_BCM96338)
     unsigned long gpio_mask = GPIO_NUM_TO_MASK(sesBtn_gpio);
-    volatile unsigned long *gpio_reg = &GPIO->GPIOio;
-#endif
-#if defined(_BCM96345_) || defined(CONFIG_BCM96345)
-    unsigned short gpio_mask = GPIO_NUM_TO_MASK(sesBtn_gpio);
-    volatile unsigned short *gpio_reg = &GPIO->GPIOio;
-#endif
-#if defined(_BCM96348_) || defined (CONFIG_BCM96348)
-    unsigned long gpio_mask = GPIO_NUM_TO_MASK(sesBtn_gpio);
-    volatile unsigned long *gpio_reg = &GPIO->GPIOio;
+    volatile unsigned long *gpio_io_reg = &GPIO->GPIOio;
 
-    if( (sesBtn_gpio & ~BP_ACTIVE_MASK) >= 32 )
+#if !defined(CONFIG_BCM96338)
+    if( (sesBtn_gpio & BP_GPIO_NUM_MASK) >= 32 )
     {
         gpio_mask = GPIO_NUM_TO_MASK_HIGH(sesBtn_gpio);
-        gpio_reg = &GPIO->GPIOio_high;
+        gpio_io_reg = &GPIO->GPIOio_high;
     }
 #endif 
                
-    if (!(*gpio_reg & gpio_mask)){
-       return POLLIN;
+    if (!(*gpio_io_reg & gpio_mask)){
+        return POLLIN;
     }  
     return 0;
 }
@@ -1126,28 +1518,20 @@ static ssize_t sesBtn_read(struct file *file,  char __user *buffer, size_t count
     volatile unsigned int event=0;
     ssize_t ret=0;     
 
-#if defined(_BCM96338_) || defined (CONFIG_BCM96338)
-    unsigned long gpio_mask = GPIO_NUM_TO_MASK(sesBtn_gpio);
-    volatile unsigned long *gpio_reg = &GPIO->GPIOio;
-#endif
-#if defined(_BCM96345_) || defined (CONFIG_BCM96345)
-    unsigned short gpio_mask = GPIO_NUM_TO_MASK(sesBtn_gpio);
-    volatile unsigned short *gpio_reg = &GPIO->GPIOio;
-#endif
-#if defined(_BCM96348_) || defined (CONFIG_BCM96348)
     unsigned long gpio_mask = GPIO_NUM_TO_MASK(sesBtn_gpio);
-    volatile unsigned long *gpio_reg = &GPIO->GPIOio;
+    volatile unsigned long *gpio_io_reg = &GPIO->GPIOio;
     
-    if( (sesBtn_gpio & ~BP_ACTIVE_MASK) >= 32 )
+#if !defined (CONFIG_BCM96338)
+    if( (sesBtn_gpio & BP_GPIO_NUM_MASK) >= 32 )
     {
         gpio_mask = GPIO_NUM_TO_MASK_HIGH(sesBtn_gpio);
-        gpio_reg = &GPIO->GPIOio_high;
+        gpio_io_reg = &GPIO->GPIOio_high;
     }
 #endif 
 
-    if(*gpio_reg & gpio_mask){
+    if(*gpio_io_reg & gpio_mask){
        BcmHalInterruptEnable(sesBtn_irq);              
-       return ret;
+           return ret;
     }  
     event = SES_EVENTS;
     __copy_to_user((char*)buffer, (char*)&event, sizeof(event));       
@@ -1193,7 +1577,7 @@ static void sesLed_ctrl(int action)
             led = kLedStateSlowBlinkContinues;                         
             break;
         case SES_LED_OFF:
-        default:
+            default:
             //printk("SES: led off\n");
             led = kLedStateOff;                                                
     }  
@@ -1214,6 +1598,294 @@ static void __exit ses_board_deinit()
 }
 #endif
 
+/***************************************************************************
+ * Dying gasp ISR and functions.
+ ***************************************************************************/
+#define KERSYS_DBG     printk
+
+#if defined(CONFIG_BCM96348) || defined(CONFIG_BCM96338)
+/* The BCM6348 cycles per microsecond is really variable since the BCM6348
+ * MIPS speed can vary depending on the PLL settings.  However, an appoximate
+ * value of 120 will still work OK for the test being done.
+ */
+#define        CYCLE_PER_US    120
+#elif defined(CONFIG_BCM96358)
+#define        CYCLE_PER_US    150
+#endif
+#define        DG_GLITCH_TO    (100*CYCLE_PER_US)
+static void __init kerSysDyingGaspMapIntr()
+{
+    unsigned long ulIntr;
+       
+    if( BpGetAdslDyingGaspExtIntr( &ulIntr ) == BP_SUCCESS ) {
+               BcmHalMapInterrupt((FN_HANDLER)kerSysDyingGaspIsr, 0, INTERRUPT_ID_DG);
+               BcmHalInterruptEnable( INTERRUPT_ID_DG );
+    }
+} 
+
+void kerSysSetWdTimer(ulong timeUs)
+{
+       TIMER->WatchDogDefCount = timeUs * (FPERIPH/1000000);
+       TIMER->WatchDogCtl = 0xFF00;
+       TIMER->WatchDogCtl = 0x00FF;
+}
+
+ulong kerSysGetCycleCount(void)
+{
+    ulong cnt; 
+#ifdef _WIN32_WCE
+    cnt = 0;
+#else
+    __asm volatile("mfc0 %0, $9":"=d"(cnt));
+#endif
+    return(cnt); 
+}
+
+static Bool kerSysDyingGaspCheckPowerLoss(void)
+{
+    ulong clk0;
+    ulong ulIntr;
+
+    ulIntr = 0;
+    clk0 = kerSysGetCycleCount();
+
+    UART->Data = 'D';
+    UART->Data = '%';
+    UART->Data = 'G';
+
+    do {
+        ulong clk1;
+        
+        clk1 = kerSysGetCycleCount();          /* time cleared */
+       /* wait a little to get new reading */
+        while ((kerSysGetCycleCount()-clk1) < CYCLE_PER_US*2)
+            ;
+     } while ((PERF->IrqStatus & (1 << (INTERRUPT_ID_DG - INTERNAL_ISR_TABLE_OFFSET))) && ((kerSysGetCycleCount() - clk0) < DG_GLITCH_TO));
+
+    if (!(PERF->IrqStatus & (1 << (INTERRUPT_ID_DG - INTERNAL_ISR_TABLE_OFFSET)))) {
+        BcmHalInterruptEnable( INTERRUPT_ID_DG );
+        KERSYS_DBG(" - Power glitch detected. Duration: %ld us\n", (kerSysGetCycleCount() - clk0)/CYCLE_PER_US);
+        return 0;
+    }
+
+    return 1;
+}
+
+static void kerSysDyingGaspShutdown( void )
+{
+    kerSysSetWdTimer(1000000);
+#if defined(CONFIG_BCM96348)
+    PERF->blkEnables &= ~(EMAC_CLK_EN | USBS_CLK_EN | USBH_CLK_EN | SAR_CLK_EN);
+#elif defined(CONFIG_BCM96358) 
+    PERF->blkEnables &= ~(EMAC_CLK_EN | USBS_CLK_EN | SAR_CLK_EN);
+#endif
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+static irqreturn_t kerSysDyingGaspIsr(int irq, void * dev_id, struct pt_regs * regs)
+#else
+static unsigned int kerSysDyingGaspIsr(void)
+#endif
+{      
+    struct list_head *pos;
+    CB_DGASP_LIST *tmp = NULL, *dsl = NULL;    
+
+    if (kerSysDyingGaspCheckPowerLoss()) {        
+
+        /* first to turn off everything other than dsl */        
+        list_for_each(pos, &g_cb_dgasp_list_head->list) {      
+            tmp = list_entry(pos, CB_DGASP_LIST, list);
+           if(strncmp(tmp->name, "dsl", 3)) {
+               (tmp->cb_dgasp_fn)(tmp->context); 
+           }else {
+               dsl = tmp;                      
+           }       
+        }  
+        
+        /* now send dgasp */
+        if(dsl)
+            (dsl->cb_dgasp_fn)(dsl->context); 
+
+        /* reset and shutdown system */
+        kerSysDyingGaspShutdown();
+
+        // If power is going down, nothing should continue!
+
+        while (1)
+            ;
+    }
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
+return( IRQ_HANDLED );
+#else
+    return( 1 );
+#endif
+}
+
+static void __init kerSysInitDyingGaspHandler( void )
+{
+    CB_DGASP_LIST *new_node;
+
+    if( g_cb_dgasp_list_head != NULL) {
+        printk("Error: kerSysInitDyingGaspHandler: list head is not null\n");
+        return;        
+    }
+    new_node= (CB_DGASP_LIST *)kmalloc(sizeof(CB_DGASP_LIST), GFP_KERNEL);
+    memset(new_node, 0x00, sizeof(CB_DGASP_LIST));
+    INIT_LIST_HEAD(&new_node->list);    
+    g_cb_dgasp_list_head = new_node; 
+               
+} /* kerSysInitDyingGaspHandler */
+
+static void __exit kerSysDeinitDyingGaspHandler( void )
+{
+    struct list_head *pos;
+    CB_DGASP_LIST *tmp; 
+       
+    if(g_cb_dgasp_list_head == NULL)
+        return;
+        
+    list_for_each(pos, &g_cb_dgasp_list_head->list) {          
+       tmp = list_entry(pos, CB_DGASP_LIST, list);
+        list_del(pos);
+       kfree(tmp);
+    }       
+
+    kfree(g_cb_dgasp_list_head);       
+    g_cb_dgasp_list_head = NULL;
+    
+} /* kerSysDeinitDyingGaspHandler */
+
+void kerSysRegisterDyingGaspHandler(char *devname, void *cbfn, void *context)
+{
+    CB_DGASP_LIST *new_node;
+
+    if( g_cb_dgasp_list_head == NULL) {
+        printk("Error: kerSysRegisterDyingGaspHandler: list head is null\n");  
+        return;    
+    }
+    
+    if( devname == NULL || cbfn == NULL ) {
+        printk("Error: kerSysRegisterDyingGaspHandler: register info not enough (%s,%x,%x)\n", devname, (unsigned int)cbfn, (unsigned int)context);            
+        return;
+    }
+       
+    new_node= (CB_DGASP_LIST *)kmalloc(sizeof(CB_DGASP_LIST), GFP_KERNEL);
+    memset(new_node, 0x00, sizeof(CB_DGASP_LIST));    
+    INIT_LIST_HEAD(&new_node->list);
+    strncpy(new_node->name, devname, IFNAMSIZ);
+    new_node->cb_dgasp_fn = (cb_dgasp_t)cbfn;
+    new_node->context = context;
+    list_add(&new_node->list, &g_cb_dgasp_list_head->list);
+    
+    printk("dgasp: kerSysRegisterDyingGaspHandler: %s registered \n", devname);
+               
+} /* kerSysRegisterDyingGaspHandler */
+
+void kerSysDeregisterDyingGaspHandler(char *devname)
+{
+    struct list_head *pos;
+    CB_DGASP_LIST *tmp;    
+    
+    if(g_cb_dgasp_list_head == NULL) {
+        printk("Error: kerSysDeregisterDyingGaspHandler: list head is null\n");
+        return;        
+    }
+
+    if(devname == NULL) {
+        printk("Error: kerSysDeregisterDyingGaspHandler: devname is null\n");
+        return;        
+    }
+    
+    printk("kerSysDeregisterDyingGaspHandler: %s is deregistering\n", devname);
+
+    list_for_each(pos, &g_cb_dgasp_list_head->list) {          
+       tmp = list_entry(pos, CB_DGASP_LIST, list);
+       if(!strcmp(tmp->name, devname)) {
+            list_del(pos);
+           kfree(tmp);
+           printk("kerSysDeregisterDyingGaspHandler: %s is deregistered\n", devname);
+           return;
+       }
+    }  
+    printk("kerSysDeregisterDyingGaspHandler: %s not (de)registered\n", devname);
+       
+} /* kerSysDeregisterDyingGaspHandler */
+
+static int ConfigCs (BOARD_IOCTL_PARMS *parms)
+{
+    int                     retv = 0;
+#if !defined(CONFIG_BCM96338)
+    int                     cs, flags;
+    cs_config_pars_t        info;
+
+    if (copy_from_user(&info, (void*)parms->buf, sizeof(cs_config_pars_t)) == 0) 
+    {
+        cs = parms->offset;
+
+        MPI->cs[cs].base = ((info.base & 0x1FFFE000) | (info.size >> 13));     
+
+        if ( info.mode == EBI_TS_TA_MODE )     // syncronious mode
+            flags = (EBI_TS_TA_MODE | EBI_ENABLE);
+        else
+        {
+            flags = ( EBI_ENABLE | \
+                (EBI_WAIT_STATES  & (info.wait_state << EBI_WTST_SHIFT )) | \
+                (EBI_SETUP_STATES & (info.setup_time << EBI_SETUP_SHIFT)) | \
+                (EBI_HOLD_STATES  & (info.hold_time  << EBI_HOLD_SHIFT )) );
+        }
+        MPI->cs[cs].config = flags;
+        parms->result = BP_SUCCESS;
+        retv = 0;
+    }
+    else
+    {
+        retv -= EFAULT;
+        parms->result = BP_NOT_DEFINED; 
+    }
+#endif
+    return( retv );
+}
+
+static void SetPll (int pll_mask, int pll_value)
+{
+    PERF->pll_control &= ~pll_mask;   // clear relevant bits
+    PERF->pll_control |= pll_value;   // and set desired value
+}
+
+static void SetGpio(int gpio, GPIO_STATE_t state)
+{
+    unsigned long gpio_mask = GPIO_NUM_TO_MASK(gpio);
+    volatile unsigned long *gpio_io_reg = &GPIO->GPIOio;
+    volatile unsigned long *gpio_dir_reg = &GPIO->GPIODir;
+    
+#if !defined (CONFIG_BCM96338)
+    if( gpio >= 32 )
+    {
+        gpio_mask = GPIO_NUM_TO_MASK_HIGH(gpio);
+        gpio_io_reg = &GPIO->GPIOio_high;
+        gpio_dir_reg = &GPIO->GPIODir_high;
+    }
+#endif 
+
+    *gpio_dir_reg |= gpio_mask;
+
+    if(state == GPIO_HIGH)
+        *gpio_io_reg |= gpio_mask;
+    else
+        *gpio_io_reg &= ~gpio_mask;
+}
+
+
+static irqreturn_t reset_isr(int irq, void *dev_id, struct pt_regs *ptregs)
+{
+    printk("\n*** Restore to Factory Default Setting ***\n\n");
+    kerSysPersistentSet( "Reset Persistent", strlen("Reset Persistent"), 0 );
+    kerSysMipsSoftReset();
+    return 0;
+}
+
+
 /***************************************************************************
  * MACRO to call driver initialization and cleanup functions.
  ***************************************************************************/
@@ -1223,6 +1895,7 @@ module_exit( brcm_board_cleanup );
 EXPORT_SYMBOL(kerSysNvRamGet);
 EXPORT_SYMBOL(dumpaddr);
 EXPORT_SYMBOL(kerSysGetMacAddress);
+EXPORT_SYMBOL(kerSysSetMacAddress);    // USR9109/9113
 EXPORT_SYMBOL(kerSysReleaseMacAddress);
 EXPORT_SYMBOL(kerSysGetSdramSize);
 EXPORT_SYMBOL(kerSysLedCtrl);
@@ -1235,7 +1908,6 @@ EXPORT_SYMBOL(BpGetRj11InnerOuterPairGpios);
 EXPORT_SYMBOL(BpGetPressAndHoldResetGpio);
 EXPORT_SYMBOL(BpGetVoipResetGpio);
 EXPORT_SYMBOL(BpGetVoipIntrGpio);
-EXPORT_SYMBOL(BpGetPcmciaResetGpio);
 EXPORT_SYMBOL(BpGetRtsCtsUartGpios);
 EXPORT_SYMBOL(BpGetAdslLedGpio);
 EXPORT_SYMBOL(BpGetAdslFailLedGpio);
@@ -1246,7 +1918,6 @@ EXPORT_SYMBOL(BpGetWanDataLedGpio);
 EXPORT_SYMBOL(BpGetPppLedGpio);
 EXPORT_SYMBOL(BpGetPppFailLedGpio);
 EXPORT_SYMBOL(BpGetVoipLedGpio);
-EXPORT_SYMBOL(BpGetWirelessExtIntr);
 EXPORT_SYMBOL(BpGetAdslDyingGaspExtIntr);
 EXPORT_SYMBOL(BpGetVoipExtIntr);
 EXPORT_SYMBOL(BpGetHpnaExtIntr);
@@ -1255,3 +1926,11 @@ EXPORT_SYMBOL(BpGetVoipChipSelect);
 EXPORT_SYMBOL(BpGetWirelessSesBtnGpio);
 EXPORT_SYMBOL(BpGetWirelessSesExtIntr);
 EXPORT_SYMBOL(BpGetWirelessSesLedGpio);
+EXPORT_SYMBOL(BpGetWirelessFlags);
+EXPORT_SYMBOL(kerSysRegisterDyingGaspHandler);
+EXPORT_SYMBOL(kerSysDeregisterDyingGaspHandler);
+EXPORT_SYMBOL(kerSysGetCycleCount);
+EXPORT_SYMBOL(kerSysSetWdTimer);
+EXPORT_SYMBOL(kerSysWakeupMonitorTask);
+EXPORT_SYMBOL(BpUpdateWirelessSromMap);
+