http://downloads.netgear.com/files/GPL/GPL_Source_V361j_DM111PSP_series_consumer_rele...
[bcm963xx.git] / bcmdrivers / opensource / char / board / bcm963xx / impl1 / board.c
index a2f380b..d408c18 100755 (executable)
@@ -191,6 +191,33 @@ static unsigned short sesBtn_gpio = BP_NOT_DEFINED;
 static unsigned short sesLed_gpio = BP_NOT_DEFINED;
 #endif
 
+//swda add,05/10/2006
+#ifdef BACKUP_WLAN_SPROM
+#define NVRAM_SPROM_TABLE_OFFSET 740
+#define NVRAM_SPROM_TABLE_SIZE 128
+static char g_SPROMData[NVRAM_SPROM_TABLE_SIZE];
+static char g_SROMSaveFlag;
+#endif
+
+#define SN_OFFSET      680
+#define SN_SIZE        31
+static char g_Serial_No[SN_SIZE];
+
+#ifdef DEFAULT_WLAN_WEP128
+#define        WEP128KEY_OFFSET        712
+#define        WEP128KEY_SIZE          13
+static char g_WEP128bit_key[WEP128KEY_SIZE];
+#endif
+
+#ifdef WLAN_ENABLE_CTRL_BUTTON
+#define GET_WLAN_ENABLE_GPIO_STATUS    0
+#define GET_BOOT_COMPLETE_FLAG 1
+#define GPIO_WLAN_ENABLE_STATE 0x40000         //GPIO 18       
+#endif
+int is_update_flash = 0;
+int IsMultiConfig = 0;
+//swda add end
+
 #if defined(MODULE)
 int init_module(void)
 {
@@ -206,7 +233,226 @@ void cleanup_module(void)
 }
 #endif //MODULE 
 
+/* Reset to default */
+#define K100MS                 ((100 * HZ) / 1000)     // ~100 ms
+#define DURATION               3*HZ                    //about 3 seconds
+// global variables:
+struct timer_list gMonitorTimerRST;
+int gMonitorTimerOnRST = FALSE;
+void MonitorTimerExpireRST(void);
+unsigned long PressTime = DURATION;
+
+#if VOXXXLOAD
+struct timer_list gMonitorTimerPSTN;
+int gMonitorTimerOnPSTN = FALSE;
+void MonitorTimerExpirePSTN(void);
+struct timer_list gMonitorTimerOFFHOOK;
+int gMonitorTimerOnOFFHOOK = FALSE;
+void MonitorTimerExpireOFFHOOK(void);
+int PSTNComingCall=0;
+int PSTNphone2OFFHOOK=0;
+int pstn_spin_lock;
+int offhook_spin_lock;
+unsigned long NoActionTimePSTN=0;
+unsigned long NoActionTimeOFFHOOK=0;
+#endif
+
+#if ODM_AUTO_PROVISION_LAN
+int autoprovisionlan=0;
+#endif
+
+int boot_complete_flag = 0;
+
+
+void MonitorTimerStartRST(void)
+{
+#if defined(CONFIG_BCM96358)||defined(CONFIG_BCM96348)||defined(CONFIG_BCM96338)
+    if (gMonitorTimerOnRST)
+        return;
+
+    init_timer(&gMonitorTimerRST);
+    gMonitorTimerRST.function = (void*)MonitorTimerExpireRST;
+    gMonitorTimerRST.expires = jiffies + K100MS;        // timer expires in ~100ms
+    add_timer(&gMonitorTimerRST);
+    gMonitorTimerOnRST = TRUE;
+#endif
+}
+
+void MonitorTimerExpireRST(void)
+{
+#if defined(CONFIG_BCM96358)
+  #define GPIO_PRESS_AND_HOLD_RESET   GPIO_NUM_TO_MASK_HIGH(36)        //GPIO 36
+    //press the GPIO_PRESS_AND_HOLD_RESET button
+    if (!(GPIO->GPIOio_high & (unsigned short)GPIO_PRESS_AND_HOLD_RESET)) {
+#elif defined(CONFIG_BCM96348)
+  #define GPIO_PRESS_AND_HOLD_RESET   0x80000000       //GPIO 31
+    //press the GPIO_PRESS_AND_HOLD_RESET button
+    if (!(GPIO->GPIOio & (unsigned int)GPIO_PRESS_AND_HOLD_RESET)) {
+#else  //CONFIG_BCM96338
+#ifdef WESTELL_GPIO
+       //printk("PERF->ExtIrqCfg = %X\n",PERF->ExtIrqCfg);
+       if ( !(PERF->ExtIrqCfg & 0x00000020) ) {
+#else
+  #define GPIO_PRESS_AND_HOLD_RESET   0x80     //GPIO 7
+    //press the GPIO_PRESS_AND_HOLD_RESET button
+    if (!(GPIO->GPIOio & (unsigned int)GPIO_PRESS_AND_HOLD_RESET)) {
+#endif
+#endif
+        if(!PressTime) PressTime = jiffies;
+        printk("\rHold Reset button for %u seconds", (jiffies - PressTime)/HZ);
+        if(jiffies - PressTime > DURATION)  { //reset to factory default setting
+#if ODM_AUTO_PROVISION_LAN
+                       if ( boot_complete_flag == 1 ) {
+                               printk("\nReset to factory default setting...\n");
+                               kerSysErasePersistent();
+                               kerSysMipsSoftReset();
+                       } else {
+               printk("\nRun auto provision on lan mode...\n");
+               kerSysLedCtrl( kLedDiag, kLedStateOff );//turn off the Diag LED(red)
+               kerSysLedCtrl( kLedPower, kLedStateFastBlinkContinues );//Power LED blinking(green)
+               autoprovisionlan=1;
+               }
+#else
+            printk("\nReset to factory default setting...\n");
+            kerSysErasePersistent();
+            //flash_reset();
+            //setDefaultBootline();
+            kerSysMipsSoftReset();
+#endif
+            gMonitorTimerOnRST = TRUE;
+            return;
+        }
+    } else {
+        PressTime = 0;
+    }
+
+    gMonitorTimerOnRST = FALSE;
+    MonitorTimerStartRST();
+}
+
+#if VOXXXLOAD
+void MonitorTimerStartPSTN(void)
+{
+#if defined(CONFIG_BCM96345)||defined(CONFIG_BCM96348)
+    if (gMonitorTimerOnPSTN)
+        return;
+
+    init_timer(&gMonitorTimerPSTN);
+    gMonitorTimerPSTN.function = (void*)MonitorTimerExpirePSTN;
+    gMonitorTimerPSTN.expires = jiffies + K100MS;        // timer expires in ~100ms
+    add_timer(&gMonitorTimerPSTN);
+    gMonitorTimerOnPSTN = TRUE;
+#endif
+}
+
+void MonitorTimerExpirePSTN(void)
+{
+#if defined(CONFIG_BCM96345)
+  #define GPIO_PSTN   0x0200
+    if (GPIO->GPIOio & (unsigned short)GPIO_PSTN){
+#else
+  #define GPIO_PSTN   0x800000
+    if (GPIO->GPIOio & (unsigned int)GPIO_PSTN){
+#endif
+       if(!PSTNComingCall) {
+           spin_lock(&pstn_spin_lock);
+           //printk("**PSTN incoming call\n");
+           PSTNComingCall=1;
+           spin_unlock(&pstn_spin_lock);
+       }
+       NoActionTimePSTN=0;
+       //printk("                                  **PSTN incoming call\n");
+    } else {
+       NoActionTimePSTN++;
+       if(NoActionTimePSTN>50) {
+             NoActionTimePSTN=0;
+             if(PSTNComingCall) {
+               spin_lock(&pstn_spin_lock);
+               //printk("**No PSTN incoming call\n");
+               PSTNComingCall=0;
+               spin_unlock(&pstn_spin_lock);
+             }
+        }
+        //printk("                                            *NO PSTN incoming call signal\n");
+     }
+    gMonitorTimerOnPSTN = FALSE;
+    MonitorTimerStartPSTN();
+}
+
+void MonitorTimerStartOFFHOOK(void)
+{
+    if (gMonitorTimerOnOFFHOOK)
+        return;
+
+    init_timer(&gMonitorTimerOFFHOOK);
+    gMonitorTimerOFFHOOK.function = (void*)MonitorTimerExpireOFFHOOK;
+    gMonitorTimerOFFHOOK.expires = jiffies + K100MS;        // timer expires in ~100ms
+    add_timer(&gMonitorTimerOFFHOOK);
+    gMonitorTimerOnOFFHOOK = TRUE;
+}
+
+void MonitorTimerExpireOFFHOOK(void)
+{
+#if defined(CONFIG_BCM96345)
+  #define GPIO_OFFHOOK   0x0002
+    if (!(GPIO->GPIOio & (unsigned short)GPIO_OFFHOOK)){
+#else
+  #define GPIO_OFFHOOK   0x400000
+    if (!(GPIO->GPIOio & (unsigned int)GPIO_OFFHOOK)){
+#endif 
+       if((!PSTNphone2OFFHOOK)&&(!PSTNComingCall)) {
+           spin_lock(&offhook_spin_lock);
+          // printk("**PSTN OFFHOOK\n");
+           PSTNphone2OFFHOOK=1;
+           spin_unlock(&offhook_spin_lock);
+       }
+       NoActionTimeOFFHOOK=0;
+    //printk("**PSTN OFFHOOK\n");
+    } else {
+       NoActionTimeOFFHOOK++;
+       if(NoActionTimeOFFHOOK>20) {
+             NoActionTimeOFFHOOK=0;
+             if(PSTNphone2OFFHOOK) {
+               spin_lock(&offhook_spin_lock);
+               //printk("**No PSTN OFFHOOK\n");
+               PSTNphone2OFFHOOK=0;
+               spin_unlock(&offhook_spin_lock);
+             }
+        }
+     //printk("              **PSTN ONHOOK\n");
+     }
+    gMonitorTimerOnOFFHOOK = FALSE;
+    MonitorTimerStartOFFHOOK();
+}
+#endif  //VOXXXLOAD
+
+//swda add,11/02/2005
+#ifdef LLL_TEST_LED
+struct timer_list gLLLTestLedTimer;
+static int gLLLTestLedTimerRunning = 0;
 
+void LLLTestLedTimerExpireFunc(void)
+{
+       kerSysLedCtrl( kLedPPP, kLedStateOff );
+       gLLLTestLedTimerRunning = 0;    
+}
+void LLLTestLedTimerStart(void)
+{
+    init_timer(&gLLLTestLedTimer);
+    gLLLTestLedTimer.function = (void*)LLLTestLedTimerExpireFunc;
+    gLLLTestLedTimer.expires = jiffies + 30*HZ;        // timer expires in ~30s
+    add_timer(&gLLLTestLedTimer);
+    gLLLTestLedTimerRunning = 1;       
+}
+void LLLTestLedTimerDelete(void)
+{
+       if (gLLLTestLedTimerRunning ) {
+               del_timer(&gLLLTestLedTimer);
+               gLLLTestLedTimerRunning = 0;
+       }
+}
+#endif
+//swda add end
 
 static int __init brcm_board_init( void )
 {
@@ -225,6 +471,8 @@ static int __init brcm_board_init( void )
      {kLedPPP, BpGetPppLedGpio, BpGetPppFailLedGpio},
      {kLedVoip, BpGetVoipLedGpio, NULL},
      {kLedSes, BpGetWirelessSesLedGpio, NULL},     
+     {kLedDiag, BpGetBootloaderStopLedGpio, NULL},
+     {kLedPower, BpGetBootloaderPowerOnLedGpio, NULL},
      {kLedEnd, NULL, NULL}
     };
 
@@ -254,6 +502,12 @@ static int __init brcm_board_init( void )
                 pLedMap->ledMask = GPIO_NUM_TO_MASK(gpio);
                 pLedMap->ledActiveLow = (gpio & BP_ACTIVE_LOW) ? 1 : 0;
                 pLedMap->ledSerial = (gpio & BP_GPIO_SERIAL) ? 1 : 0;
+                //swda add,05/17/2006
+                if (pInfo->ledName == kLedPower)
+                       pLedMap->ledInitState = kLedStateOff;
+                if (pInfo->ledName == kLedDiag)
+                       pLedMap->ledInitState = kLedStateOn;
+                //swda add end
             }
             if( pInfo->bpFuncFail && (*pInfo->bpFuncFail)(&gpio)==BP_SUCCESS &&
                 gpio != BP_HW_DEFINED_AH && gpio != BP_HW_DEFINED_AL )
@@ -266,7 +520,7 @@ static int __init brcm_board_init( void )
             if( pLedMap->ledName != kLedEnd )
                 pLedMap++;
         }
-
+        
         if( BpGetEthernetMacInfo( &EnetInfo, 1 ) == BP_SUCCESS )
         {
             if( EnetInfo.usGpioPhyLinkSpeed != BP_NOT_DEFINED )
@@ -298,6 +552,32 @@ static int __init brcm_board_init( void )
             BcmHalInterruptEnable(pah_irq);
         }
     }
+    //Start the timer to detect the GPIO_PRESS_AND_HOLD_RESET
+#ifdef CONFIG_BCM96338 //swda add
+       GPIO->GPIODir &= 0xFFFFFF7F;//GPIO 7 used as reset to default pin, set GPIO 7 as input
+        
+       GPIO->GPIODir |= 0x0004;        //set GPIO2 as output pin,so that we can control GPIO4 value 
+       GPIO->GPIOio |= 0x0004;         //pull GPIO2 high, so that we can control ppp led
+#endif
+
+#ifdef CONFIG_BCM96348
+       GPIO->GPIODir |= 0x0010;        //set GPIO4 as output pin,so that we can control GPIO4 value 
+       GPIO->GPIOio |= 0x0010;         //pull GPIO4 high, so that we can control ppp led via GPIO3
+#endif
+
+#ifdef CONFIG_BCM96358
+    GPIO->GPIODir_high &= (~GPIO_NUM_TO_MASK_HIGH(36));//GPIO 36 used as reset to default pin, set GPIO 36 as input
+#endif
+
+#ifdef WLAN_ENABLE_CTRL_BUTTON
+       GPIO->GPIODir &= (unsigned int)(~GPIO_WLAN_ENABLE_STATE);//GPIO 18 used to inform wlan to turn off, so set GPIO 18 as input pin
+#endif
+
+    MonitorTimerStartRST();
+#if VOXXXLOAD
+    MonitorTimerStartPSTN();
+    MonitorTimerStartOFFHOOK();
+#endif
 
     return ret;
 } 
@@ -305,8 +585,11 @@ static int __init brcm_board_init( void )
 void __init InitNvramInfo( void )
 {
     PNVRAM_DATA pNvramData = (PNVRAM_DATA) get_nvram_start_addr();
+#if 0 //BRCM orig
     unsigned long ulNumMacAddrs = pNvramData->ulNumMacAddrs;
-
+#else
+    unsigned long ulNumMacAddrs = 12;  /* We skip what the user set up.  change it max 12, each PVC use one but we change first byte */
+#endif
     if( ulNumMacAddrs > 0 && ulNumMacAddrs <= NVRAM_MAC_COUNT_MAX )
     {
         unsigned long ulNvramInfoSize =
@@ -321,7 +604,11 @@ void __init InitNvramInfo( void )
                 ulPsiSize = NVRAM_PSI_DEFAULT;
             memset( g_pNvramInfo, 0x00, ulNvramInfoSize );
             g_pNvramInfo->ulPsiSize = ulPsiSize * 1024;
+#if 0 //BRCM orig
             g_pNvramInfo->ulNumMacAddrs = pNvramData->ulNumMacAddrs;
+#else
+            g_pNvramInfo->ulNumMacAddrs = 12;
+#endif
             memcpy( g_pNvramInfo->ucaBaseMacAddr, pNvramData->ucaBaseMacAddr,
                 NVRAM_MAC_ADDRESS_LEN );
             g_pNvramInfo->ulSdramSize = getMemorySize();
@@ -332,6 +619,33 @@ void __init InitNvramInfo( void )
     else
         printk("ERROR - Invalid number of MAC addresses (%ld) is configured.\n",
             ulNumMacAddrs);
+
+//swda add,04/08/2005
+#ifdef BACKUP_WLAN_SPROM
+       g_SROMSaveFlag = pNvramData->sprom_saved_flag;
+       kerSysNvRamGet(g_SPROMData, NVRAM_SPROM_TABLE_SIZE, NVRAM_SPROM_TABLE_OFFSET);
+#endif
+
+       kerSysNvRamGet(g_Serial_No, SN_SIZE, SN_OFFSET);
+
+#ifdef DEFAULT_WLAN_WEP128
+       kerSysNvRamGet(g_WEP128bit_key,WEP128KEY_SIZE,WEP128KEY_OFFSET);
+       {       //check if valid ASCII string
+               int key_index,valid_key;
+               
+               valid_key = 1;
+               for (key_index=0;key_index<WEP128KEY_SIZE;key_index++) {
+                       //printable ASCII character 0x21~0x7E
+                       if ( g_WEP128bit_key[key_index]<0x21 || g_WEP128bit_key[key_index]>0x7e ) {
+                               valid_key = 0;
+                               break;
+                       }       
+               }
+               if (!valid_key) 
+                       strcpy(g_WEP128bit_key,"0000000000000");        
+       }
+#endif
+//swda add end
 }
 
 void __exit brcm_board_cleanup( void )
@@ -507,6 +821,18 @@ int kerSysGetMacAddress( unsigned char *pucaMacAddr, unsigned long ulId )
     PMAC_ADDR_INFO pMaiFreeNoId = NULL;
     PMAC_ADDR_INFO pMaiFreeId = NULL;
     unsigned long i = 0, ulIdxNoId = 0, ulIdxId = 0, baseMacAddr = 0;
+    unsigned long ulWanBaseIdxId = 1;//swda add,05/08/2006
+
+//swda add,05/08/2006    
+#ifdef BRCM_DRIVER_USB
+       ulWanBaseIdxId += 2;//ulWanBaseIdxId = 3
+#endif
+#ifdef WIRELESS
+#ifndef BACKUP_WLAN_SPROM      //only wlan on board need mac assignment
+       ulWanBaseIdxId += 1;//ulWanBaseIdxId = 2 or 4
+#endif
+#endif
+//swda add end
 
     /* baseMacAddr = last 3 bytes of the base MAC address treated as a 24 bit integer */
     memcpy((unsigned char *) &baseMacAddr,
@@ -559,21 +885,33 @@ int kerSysGetMacAddress( unsigned char *pucaMacAddr, unsigned long ulId )
         memcpy(pucaMacAddr, g_pNvramInfo->ucaBaseMacAddr,NVRAM_MAC_ADDRESS_LEN);
         if( pMaiFreeNoId )
         {
-            baseMacAddr = (baseMacAddr + ulIdxNoId) << 8;
-            memcpy( pucaMacAddr, g_pNvramInfo->ucaBaseMacAddr,
-                constMacAddrIncIndex);
-            memcpy( pucaMacAddr + constMacAddrIncIndex, (unsigned char *)
-                &baseMacAddr, NVRAM_MAC_ADDRESS_LEN - constMacAddrIncIndex );
+               //swda modify,05/08/2006
+               if ( ulIdxNoId >= ulWanBaseIdxId ) {
+                       pucaMacAddr[0] += (ulIdxNoId-ulWanBaseIdxId)*8+2;
+               } else {
+               baseMacAddr = (baseMacAddr + ulIdxNoId) << 8;
+               memcpy( pucaMacAddr, g_pNvramInfo->ucaBaseMacAddr,
+                       constMacAddrIncIndex);
+               memcpy( pucaMacAddr + constMacAddrIncIndex, (unsigned char *)
+                       &baseMacAddr, NVRAM_MAC_ADDRESS_LEN - constMacAddrIncIndex );
+            }
+            //swda modify end
             pMaiFreeNoId->ulId = ulId;
             pMaiFreeNoId->chInUse = 1;
         }
         else
         {
-            baseMacAddr = (baseMacAddr + ulIdxId) << 8;
-            memcpy( pucaMacAddr, g_pNvramInfo->ucaBaseMacAddr,
-                constMacAddrIncIndex);
-            memcpy( pucaMacAddr + constMacAddrIncIndex, (unsigned char *)
-                &baseMacAddr, NVRAM_MAC_ADDRESS_LEN - constMacAddrIncIndex );
+               //swda modify,05/08/2006
+               if ( ulIdxId >= ulWanBaseIdxId ) {
+                       pucaMacAddr[0] += (ulIdxId-ulWanBaseIdxId)*8+2;
+               } else {
+               baseMacAddr = (baseMacAddr + ulIdxId) << 8;
+               memcpy( pucaMacAddr, g_pNvramInfo->ucaBaseMacAddr,
+                       constMacAddrIncIndex);
+               memcpy( pucaMacAddr + constMacAddrIncIndex, (unsigned char *)
+                       &baseMacAddr, NVRAM_MAC_ADDRESS_LEN - constMacAddrIncIndex );
+            }
+            //swda modify end
             pMaiFreeId->ulId = ulId;
             pMaiFreeId->chInUse = 1;
         }
@@ -655,7 +993,8 @@ void kerSysWakeupMonitorTask( void )
     if( g_monitor_task )
         wake_up_process( g_monitor_task );
 }
-
+//#if defined(CONFIG_BCM96358) 
+#if 0
 static PFILE_TAG getTagFromPartition(int imageNumber)
 {
     static unsigned char sectAddr1[sizeof(FILE_TAG)];
@@ -832,9 +1171,11 @@ static int flashFsKernelImage( int destAddr, unsigned char *imagePtr,
     }
 
     UpdateImageSequenceNumber( ((PFILE_TAG) tagFs)->imageSequence );
+/* we do not modify Tag so crc does not need to modify */
     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 )
     {
@@ -859,12 +1200,67 @@ static int flashFsKernelImage( int destAddr, unsigned char *imagePtr,
 
     return(status);
 }
+#else
+static PFILE_TAG getBootImageTag(void)
+{
+    int i;
+    int totalBlks = flash_get_numsectors();
+    int totalSize = flash_get_total_size();
+    int startblock,redo;
+    UINT32 crc;
+    unsigned char *sectAddr;
+    unsigned char bootf1,bootf2,nbootflag=0;
+
+    PFILE_TAG pTag;
+    int totalImageSize = 0;/* vic add to check image crc */
+
+redo=1;
+if (totalSize == 0x800000) {
+    bootf1 = *(unsigned char*) (FLASH_BASE+(totalSize/2)-1); /*see design note 4MB flash layout*/
+    bootf2 = *(unsigned char*) (FLASH_BASE+totalSize-FLASH_RESERVED_AT_END -1);
+    printk("bootf %02x/%02x  ",bootf1,bootf2);
+    if ((bootf1 >> 2) == 0 && bootf1 ) 
+    {
+        if ((bootf2 >> 2) == 0 && bootf2 ) 
+        { /* both are valid */
+          if ((bootf1+1) == bootf2 || ((bootf1+1) >>2 == bootf2) ) nbootflag=1; /*bank2*/
+          if ((bootf2+1) == bootf1 || ((bootf2+1) >>2 == bootf1) ) nbootflag=0; /*bank1*/ 
+        } 
+        else nbootflag = 0; /* bank2 invalid bank1 valid */
+    }
+    else  if ((bootf2 >> 2) == 0 && bootf2) nbootflag =1; /*bank 1 invalid,bank 2 valid*/
+    else  nbootflag=0; /* bank1 bank2 both invalid */
+    
+    //printf("bootf1 %x bootf2 %x\n", bootf1,bootf2);
+}
+else nbootflag=0; 
+
+recheck:
+
+startblock = nbootflag?flash_get_blk(FLASH_BASE+(totalSize/2)):flash_get_blk(FLASH_BASE+FLASH_LENGTH_BOOT_ROM);
+//printk("bootbank %d,start to scan from %d block\n",startblock);
+
+    // start from 2nd blk, assume 1st one is always CFE
+    for (i = startblock; i < startblock + (totalBlks>>1) ; i++)
+    {
+        sectAddr =  flash_get_memptr((byte) i);
+        crc = CRC32_INIT_VALUE;
+        crc = getCrc32(sectAddr, (UINT32)TAG_LEN-TOKEN_LEN, crc);      
+        pTag = (PFILE_TAG) sectAddr;
+        if (crc == (UINT32)(*(UINT32*)(pTag->tagValidationToken))) 
+           return pTag;
+    }
+    return (PFILE_TAG) NULL;
+
+}
+#endif
 
+#if defined(CONFIG_BCM96358) 
 PFILE_TAG kerSysImageTagGet(void)
 {
     return( getBootImageTag() );
 }
-
+#endif
 
 //********************************************************************************************
 // misc. ioctl calls come to here. (flash, led, reset, kernel memory access, etc.)
@@ -875,6 +1271,13 @@ static int board_ioctl( struct inode *inode, struct file *flip,
     int ret = 0;
     BOARD_IOCTL_PARMS ctrlParms;
     unsigned char ucaMacAddr[NVRAM_MAC_ADDRESS_LEN];
+    
+#if defined(CONFIG_BCM96338) || defined(CONFIG_BCM96348) || defined(CONFIG_BCM96358)
+    int totalSize = flash_get_total_size();
+    unsigned char nbootflag; /*vic add for bootflag check*/
+    int allowedSize;
+    static unsigned char HasWriteBinfs=0;
+#endif
 
     switch (command) 
     {
@@ -887,9 +1290,27 @@ static int board_ioctl( struct inode *inode, struct file *flip,
             {
                 NVRAM_DATA SaveNvramData;
                 PNVRAM_DATA pNvramData = (PNVRAM_DATA) get_nvram_start_addr();
+//swda add,05/11/2006
+#ifdef BACKUP_WLAN_SPROM
+                               char SaveNvramData_sprom[NVRAM_SPROM_TABLE_SIZE];
+#endif
 
+                               char Serial_No[SN_SIZE];
+
+#ifdef DEFAULT_WLAN_WEP128
+                               char WEP128bit_key[WEP128KEY_SIZE];
+#endif
+//swda add end
                 switch (ctrlParms.action)
                 {
+    /*==== add by Andrew (2004/09/14)====*/
+#if defined(CFG_XFER_TO_FACDEFLT)
+                                       case FACTDEFLT:
+                                               ret = kerSysFactDefltSet(ctrlParms.string, ctrlParms.strLen, ctrlParms.offset);
+                                               break;
+#endif
+    /*==== end ====*/
+
                     case SCRATCH_PAD:
                         if (ctrlParms.offset == -1)
                               ret =  kerSysScratchPadClearAll();
@@ -898,12 +1319,69 @@ static int board_ioctl( struct inode *inode, struct file *flip,
                         break;
 
                     case PERSISTENT:
+                                               //swda add,11/30/2006
+                        //swda: Power Led flash red
+                        kerSysLedCtrl(kLedPower, kLedStateOff);//green off
+                        kerSysLedCtrl(kLedDiag, kLedStateOn);//red on
+                        kerSysSetUpgradeState(2); //upgrade configuration start
+                                               //swda add end                                                             
                         ret = kerSysPersistentSet(ctrlParms.string, ctrlParms.strLen, ctrlParms.offset);
+                                               //swda add,11/30/2006
+                        //swda: Power Led solid green
+                        kerSysSetUpgradeState(0);//upgrade configuration end
+                        if ( IsMultiConfig || (!boot_complete_flag) ) {        
+                               kerSysLedCtrl(kLedDiag, kLedStateOn);//red on
+                        } else {
+                               kerSysLedCtrl(kLedDiag, kLedStateOff);//red
+                               kerSysLedCtrl(kLedPower, kLedStateOn);//green
+                        }
+                                               //swda add end
                         break;
                 
                     case NVRAM:
+                        if (ctrlParms.offset == 1024 + 10) {
+                            unsigned long memType=*(unsigned long *)ctrlParms.string;   
+                            printk("set memtype %d\n",memType);                          
+                            kerSysMemoryTypeSet(FLASH_BASE,(char *) &memType, sizeof(int));
+                        }
+                        else if (ctrlParms.offset == 1024 + 20) {
+                            unsigned long memType=*(unsigned long *)ctrlParms.string;
+                            printk("set Thread num %d\n");                             
+                            kerSysThreadNumSet(FLASH_BASE,(char *) &memType, sizeof(int));     
+                        }
+                        else                           
                         ret = kerSysNvRamSet(ctrlParms.string, ctrlParms.strLen, ctrlParms.offset);
                         break;
+#if defined(CONFIG_BCM96348)                        
+                    case BCM_IMAGE_BINFS:
+                    
+ //printk("will flash bin fs offset at 0%x\n",ctrlParms.offset);
+                        if ( totalSize < 8*1024*1024 ) {
+                            printk(" Bin file system only is allowed for 8MB not for %d MB Flash\n",flash_get_total_size()/0x100000);
+                            ret = -1;
+                            break;
+                        }   
+                     
+                            
+                        if( ctrlParms.strLen <= 0 || ctrlParms.strLen > 4*1024*1024 - 64*1024)
+                        {
+                            printk("Illegal root file system size [%d]. Size allowed: [%d]\n",
+                                ctrlParms.strLen,  allowedSize);
+                            ret = -1;
+                            break;
+                        }
+                        //swda: Power Led flash red
+                        kerSysLedCtrl(kLedPower, kLedStateOff);//green
+                        kerSysLedCtrl(kLedDiag, kLedStateOn);//red 
+                        kerSysSetUpgradeState(1); //upgrade start                                                                                                                                            
+                        ret = kerSysBcmImageSet(ctrlParms.offset, ctrlParms.string, ctrlParms.strLen);
+                        //swda: Power Led solid green
+                        kerSysLedCtrl(kLedDiag, kLedStateOff);//red
+                        kerSysLedCtrl(kLedPower, kLedStateOn);//green
+                        kerSysSetUpgradeState(0);//upgrade end
+                        HasWriteBinfs = 1;
+                        break;    
+#endif
 
                     case BCM_IMAGE_CFE:
                         if( ctrlParms.strLen <= 0 || ctrlParms.strLen > FLASH_LENGTH_BOOT_ROM )
@@ -913,10 +1391,25 @@ static int board_ioctl( struct inode *inode, struct file *flip,
                             ret = -1;
                             break;
                         }
-
+#if defined(CONFIG_BCM96348) || defined(CONFIG_BCM96338) || defined(CONFIG_BCM96358)
+                        //swda: Power Led flash red
+                        kerSysLedCtrl(kLedPower, kLedStateOff);//green
+                        kerSysLedCtrl(kLedDiag, kLedStateOn);//red
+                        kerSysSetUpgradeState(1); //upgrade start
+#endif
                         // save NVRAM data into a local structure
                         memcpy( &SaveNvramData, pNvramData, sizeof(NVRAM_DATA) );
-
+//swda add,05/11/2006
+#ifdef BACKUP_WLAN_SPROM     //save NVRAM sprom data into a local structure                   
+                        kerSysNvRamGet(SaveNvramData_sprom, NVRAM_SPROM_TABLE_SIZE, NVRAM_SPROM_TABLE_OFFSET);
+#endif       
+                                       //save Serial Number into a local structure
+                        kerSysNvRamGet(Serial_No, SN_SIZE, SN_OFFSET);
+
+#ifdef DEFAULT_WLAN_WEP128  //save WEP 128bit key into a local structure
+                        kerSysNvRamGet(WEP128bit_key,WEP128KEY_SIZE,WEP128KEY_OFFSET);
+#endif
+//swda add end
                         // set memory type field
                         BpGetSdramSize( (unsigned long *) &ctrlParms.string[SDRAM_TYPE_ADDRESS_OFFSET] );
                         // set thread number field
@@ -930,14 +1423,228 @@ static int board_ioctl( struct inode *inode, struct file *flip,
                         {
                             kerSysNvRamSet((char *) &SaveNvramData, sizeof(SaveNvramData), 0);
                         }
+//swda add,05/11/2006
+#ifdef BACKUP_WLAN_SPROM    //swda : restore nvram sprom data
+                        kerSysNvRamSet(SaveNvramData_sprom, NVRAM_SPROM_TABLE_SIZE, NVRAM_SPROM_TABLE_OFFSET);
+
+#endif       
+                                       //restore Serial Number
+                        kerSysNvRamSet(Serial_No, SN_SIZE, SN_OFFSET);
+
+#ifdef DEFAULT_WLAN_WEP128 //restore WEP 128bit key
+                        kerSysNvRamSet(WEP128bit_key,WEP128KEY_SIZE,WEP128KEY_OFFSET);
+#endif
+//swda add end 
+#if defined(CONFIG_BCM96348) || defined(CONFIG_BCM96338) || defined(CONFIG_BCM96358)
+                        //swda: Power Led solid green
+                        kerSysLedCtrl(kLedDiag, kLedStateOff);//red
+                        kerSysLedCtrl(kLedPower, kLedStateOn);//green
+                        kerSysSetUpgradeState(0); //upgrade end
+#endif                     
                         break;
                         
                     case BCM_IMAGE_FS:
+#if 0 /* defined(CONFIG_BCM96358) */
+                        //swda: Power Led flash red
+                        kerSysLedCtrl(kLedPower, kLedStateOff);//green
+                        kerSysLedCtrl(kLedDiag, kLedStateOn);//red
+                        kerSysSetUpgradeState(1); //upgrade start
+
                         if( (ret = flashFsKernelImage( ctrlParms.offset,
                             ctrlParms.string, ctrlParms.strLen)) == 0 )
                         {
+                            //swda: Power Led solid green
+                            kerSysLedCtrl(kLedDiag, kLedStateOff);//red
+                            kerSysLedCtrl(kLedPower, kLedStateOn);//green
+                            kerSysSetUpgradeState(0); //upgrade end
+
                             kerSysMipsSoftReset();
+
                         }
+#else
+                        allowedSize = (int) flash_get_total_size() - \
+                            FLASH_RESERVED_AT_END - TAG_LEN - FLASH45_LENGTH_BOOT_ROM;
+                        if( ctrlParms.strLen <= 0 || ctrlParms.strLen > allowedSize)
+                        {
+                            printk("Illegal root file system size [%d]. Size allowed: [%d]\n",
+                                ctrlParms.strLen,  allowedSize);
+                            ret = -1;
+                            break;
+                        }
+
+                        //swda: Power Led flash red
+                        kerSysLedCtrl(kLedPower, kLedStateOff);//green
+                        kerSysLedCtrl(kLedDiag, kLedStateOn);//red
+                        kerSysSetUpgradeState(1); //upgrade start
+
+                        //printk("\nflash fs offset at 0%x\n",ctrlParms.offset);
+              
+#if defined(CONFIG_BCM96348)                        
+                        {
+                           unsigned char* bootflag;
+                           PFILE_TAG pTag;
+                           bootflag=flash_get_memptr((byte) 0);
+                           int tagVer, curVer;
+                           
+                           pTag = (PFILE_TAG) ctrlParms.string;
+                           //printk("got %s cur %s\n", pTag->FlashLayoutVersion,BCM_FLASH_LAYOUT_VER);
+                           tagVer = (u_int32_t) simple_strtoul(pTag->FlashLayoutVersion, NULL, 10);
+                                  curVer = (u_int32_t) simple_strtoul(BCM_FLASH_LAYOUT_VER, NULL, 10);
+                           
+                           if (totalSize == 0x800000) 
+                              if (curVer > 4 && tagVer < 5) { /* 5 start from 3.28u */
+                                 printk("Not allow to downgrade to flash layout version less than 5\n"); 
+                              ret = -1;
+                              break;
+                           }                   
+                                                     
+                           if (totalSize == 0x800000) {nbootflag=*bootflag;printk("\nget bootflag %d\n",*bootflag);}
+                           else nbootflag=1; 
+                                                                       
+                           if (((curVer >= 4) && ( tagVer <4 )) || HasWriteBinfs ) { /* flash layout 3 -> 4 will knows dualimage@8M */
+                                 printk("flash layout curVer %x tagVer %x\n", curVer,tagVer);
+                               /* ?? erase bootflag to avoid choose an broken partition to start */
+                                 if (!HasWriteBinfs) { printk("Not "); kerSysErasePS1();}
+                                 printk("Has Writtten Binfs\n");   
+                                    nbootflag=1; /* boot from bf800000 will flash bfc00000 */
+                               /* will erase bf800000 after image(bfc00000) upgrade successfully */
+                           }
+                           
+                           /*  nbootflag=1;  FAKE!!!! always flash bfc00000 */
+
+                           /* bootflag is 0 means boot from bfc00000 will flash bf800000 */
+                           if (nbootflag==0) {                                 
+                               u_int32_t rootfs_addr,kernel_addr,tagCrc;                               
+                                 //printk("rootfs addr %s kernelAddress %s\n", pTag->rootfsAddress,pTag->kernelAddress);
+                                 rootfs_addr = (u_int32_t) simple_strtoul(pTag->rootfsAddress, NULL, 10);
+                              kernel_addr = (u_int32_t) simple_strtoul(pTag->kernelAddress, NULL, 10);
+                              //printk("rootfs addr %x kernelAddress %x\n", rootfs_addr,kernel_addr);
+                              rootfs_addr-=0x400000;
+                              sprintf(pTag->rootfsAddress,"%lu",(unsigned long) rootfs_addr);
+                              kernel_addr-=0x400000;
+                              sprintf(pTag->kernelAddress,"%lu",(unsigned long) kernel_addr);
+                              // get tag crc
+                              //printk("rootfs addr %x kernelAddress %x\n", rootfs_addr,kernel_addr);
+                                         tagCrc = CRC32_INIT_VALUE;
+                                         tagCrc = getCrc32((byte*)pTag, TAG_LEN-TOKEN_LEN, tagCrc);
+                                         memcpy(pTag->tagValidationToken, (byte*)&tagCrc, CRC_LEN);
+                                 ctrlParms.offset-=0x400000;
+                                 nbootflag=1;
+                           
+                           }
+                           else  nbootflag=0;  /* will flash bfc00000 if bootflag is 1(bf800000 is valid) or 2(binfs) or else */
+                         
+                        }
+#endif
+
+#if defined(CONFIG_BCM96338) || defined(CONFIG_BCM96358)
+       {
+               PFILE_TAG pTag;         
+               unsigned char bootf1,bootf2;
+               int tagVer, curVer;
+                           
+                 pTag = (PFILE_TAG) ctrlParms.string;
+                 printk("\nImagelen %d\n", ctrlParms.strLen);
+                 tagVer = (u_int32_t) simple_strtoul(pTag->FlashLayoutVersion, NULL, 10);
+                curVer = (u_int32_t) simple_strtoul(BCM_FLASH_LAYOUT_VER, NULL, 10);
+                
+#if defined(CONFIG_BCM96338)                    
+                if (totalSize == 0x400000) 
+#endif
+#if defined(CONFIG_BCM96358)
+                                if (totalSize == 0x800000) 
+#endif
+                   if (curVer > 4 && tagVer < 5) { /* 5 start from 3.28u */
+                          printk("Not allow to downgrade to flash layout version less than 5\n"); 
+                       ret = -1;
+                       break;
+                   }  
+#if defined(CONFIG_BCM96338)                    
+           if ((totalSize == 0x400000) && (ctrlParms.strLen <= (0x200000 - TAG_LEN - FLASH45_LENGTH_BOOT_ROM -1) ) ) { /* get bootflag to compare where to boot from */ 
+#endif
+#if defined(CONFIG_BCM96358)
+                       if ((totalSize == 0x800000) && (ctrlParms.strLen <= (0x400000 - TAG_LEN - FLASH45_LENGTH_BOOT_ROM -1) ) ) { /* get bootflag to compare where to boot from */ 
+#endif
+
+                  bootf1 = *(unsigned char*) (FLASH_BASE+(totalSize/2)-1); /*see design note 4MB flash layout*/
+                  bootf2 = *(unsigned char*) (FLASH_BASE+totalSize-FLASH_RESERVED_AT_END-1);
+                  if ((bootf1 >> 2) == 0 && bootf1 ) {
+                   if ((bootf2 >> 2) == 0 && bootf2 ) { /* both are valid */
+                     if ((bootf1+1) == bootf2 || ((bootf1+1) >>2 == bootf2) ) nbootflag=1; /*bank2*/
+                     if ((bootf2+1) == bootf1 || ((bootf2+1) >>2 == bootf1) ) nbootflag=0; /*bank1*/ 
+                    } else nbootflag = 0; /* bank2 invalid bank1 valid */
+               } else  if ((bootf2 >> 2) == 0 && bootf2) nbootflag =1; /*bank 1 invalid,bank 2 valid*/
+                   else  nbootflag=0; /* bank1 bank2 both invalid */   
+                   printk("\nbflag %x %x,bbank %d\n",bootf1,bootf2, nbootflag);
+            } else { nbootflag=2; kerSysErasePS1(); }
+                
+#if defined(CONFIG_BCM96338)                    
+                if (totalSize == 0x400000)
+#endif
+#if defined(CONFIG_BCM96358)
+                               if (totalSize == 0x800000) 
+#endif
+                if ((curVer >= 4) && ( tagVer <4 )) { /* flash layout 3 -> 4 will knows dualimage@8M */
+                    printk("flash layout curVer %x tagVer %x\n", curVer,tagVer);
+                    /* ?? erase bootflag to avoid choose an broken partition to start */
+                    kerSysErasePS1();
+                    nbootflag=2; /* skip set bootflag for bank 2 */
+                }                
+                
+                if (nbootflag==0) { /*boot from bank0 will flash bank1*/
+
+                        u_int32_t rootfs_addr,kernel_addr,tagCrc;
+                                                               
+                        //printk("rootfs addr %s kernelAddress %s\n", pTag->rootfsAddress,pTag->kernelAddress);
+                        rootfs_addr = (u_int32_t) simple_strtoul(pTag->rootfsAddress, NULL, 10);
+                        kernel_addr = (u_int32_t) simple_strtoul(pTag->kernelAddress, NULL, 10);
+                        //printk("rootfs addr %x kernelAddress %x\n", rootfs_addr,kernel_addr);
+                        
+                       // Update rootfsAddr to point to the second boot partition.
+                       sprintf(((PFILE_TAG) pTag)->kernelAddress, "%lu",
+                               (unsigned long) (kernel_addr+(totalSize/2)-FLASH_LENGTH_BOOT_ROM) );
+
+                       sprintf(((PFILE_TAG) pTag)->rootfsAddress, "%lu",
+                               (unsigned long) (rootfs_addr+(totalSize/2)-FLASH_LENGTH_BOOT_ROM));
+            
+                        // get tag crc
+                        //printk("rootfs addr %x kernelAddress %x\n", rootfs_addr,kernel_addr);
+                       tagCrc = CRC32_INIT_VALUE;
+                       tagCrc = getCrc32((byte*)pTag, TAG_LEN-TOKEN_LEN, tagCrc);
+                       memcpy(pTag->tagValidationToken, (byte*)&tagCrc, CRC_LEN);
+                        ctrlParms.offset+=((totalSize/2)-FLASH_LENGTH_BOOT_ROM );
+                        nbootflag=1;                                                                   
+               } else if ( nbootflag ==1 ) nbootflag=0;                                
+       }
+#endif                       
+                        ctrlParms.offset+= BOOT_OFFSET;
+                        printk("Flashing@0%8x\n",ctrlParms.offset);                                                                                                                                                
+                        ret = kerSysBcmImageSet(ctrlParms.offset, ctrlParms.string, ctrlParms.strLen);
+
+#if defined(CONFIG_BCM96348)                         
+                        if (totalSize == 0x800000)
+                         if(HasWriteBinfs)  kerSysBootFlagSet(0x02);
+                         else  kerSysBootFlagSet(nbootflag);
+
+#endif
+#if defined(CONFIG_BCM96338)
+                       if (totalSize == 0x400000 && (nbootflag<2) ) 
+                           kerSysBootFlagSet(nbootflag);
+
+#endif                    
+#if defined(CONFIG_BCM96358)
+                       if (totalSize == 0x800000 && (nbootflag<2) ) 
+                           kerSysBootFlagSet(nbootflag);
+
+#endif  
+                 
+                        //swda: Power Led solid green
+                        kerSysLedCtrl(kLedDiag, kLedStateOff);//red
+                        kerSysLedCtrl(kLedPower, kLedStateOn);//green
+                        kerSysSetUpgradeState(0); //upgrade end
+                        kerSysMipsSoftReset();
+#endif
+
                         break;
 
                     case BCM_IMAGE_KERNEL:  // not used for now.
@@ -950,9 +1657,25 @@ static int board_ioctl( struct inode *inode, struct file *flip,
                             break;
                         }
 
+#if defined(CONFIG_BCM96348) || defined(CONFIG_BCM96338) || defined(CONFIG_BCM96358)
+                        //swda: Power Led flash red
+                        kerSysLedCtrl(kLedPower, kLedStateOff);//green
+                        kerSysLedCtrl(kLedDiag, kLedStateOn);//red
+                        kerSysSetUpgradeState(1); //upgrade start
+#endif
                         // save NVRAM data into a local structure
                         memcpy( &SaveNvramData, pNvramData, sizeof(NVRAM_DATA) );
-
+//swda add,05/11/2006
+#ifdef BACKUP_WLAN_SPROM     //save NVRAM sprom data into a local structure                   
+                        kerSysNvRamGet(SaveNvramData_sprom, NVRAM_SPROM_TABLE_SIZE, NVRAM_SPROM_TABLE_OFFSET);
+#endif       
+                                               //save Serial Number into a local structure
+                        kerSysNvRamGet(Serial_No, SN_SIZE, SN_OFFSET);
+
+#ifdef DEFAULT_WLAN_WEP128  //save WEP 128bit key into a local structure
+                        kerSysNvRamGet(WEP128bit_key,WEP128KEY_SIZE,WEP128KEY_OFFSET);
+#endif
+//swda add end
                         if (ctrlParms.offset == 0) {
                             ctrlParms.offset = FLASH_BASE;
                         }
@@ -964,7 +1687,25 @@ static int board_ioctl( struct inode *inode, struct file *flip,
                         {
                             kerSysNvRamSet((char *) &SaveNvramData, sizeof(SaveNvramData), 0);
                         }
+//swda add,05/11/2006
+#ifdef BACKUP_WLAN_SPROM    //swda : restore nvram sprom data
+                        kerSysNvRamSet(SaveNvramData_sprom, NVRAM_SPROM_TABLE_SIZE, NVRAM_SPROM_TABLE_OFFSET);
+
+#endif       
+                                               //restore Serial Number
+                        kerSysNvRamSet(Serial_No, SN_SIZE, SN_OFFSET);
 
+#ifdef DEFAULT_WLAN_WEP128 //restore WEP 128bit key
+                        kerSysNvRamSet(WEP128bit_key,WEP128KEY_SIZE,WEP128KEY_OFFSET);
+#endif
+//swda add end
+
+#if defined(CONFIG_BCM96348) || defined(CONFIG_BCM96338) || defined(CONFIG_BCM96358)
+                        //swda: Power Led solid green
+                        kerSysLedCtrl(kLedDiag, kLedStateOff);//red
+                        kerSysLedCtrl(kLedPower, kLedStateOn);//green
+                        kerSysSetUpgradeState(0); //upgrade end
+#endif                   
                         kerSysMipsSoftReset();
                         break;
 
@@ -985,6 +1726,14 @@ static int board_ioctl( struct inode *inode, struct file *flip,
             {
                 switch (ctrlParms.action)
                 {
+    /*==== add by Andrew (2004/09/14)====*/
+#if defined(CFG_XFER_TO_FACDEFLT)
+                                       case FACTDEFLT:
+                                               ret = kerSysFactDefltGet(ctrlParms.string, ctrlParms.strLen, ctrlParms.offset);
+                                               break;
+#endif
+    /*==== end ====*/
+
                     case SCRATCH_PAD:
                         ret = kerSysScratchPadGet(ctrlParms.string, ctrlParms.buf, ctrlParms.offset);
                         break;
@@ -1393,7 +2142,117 @@ static int board_ioctl( struct inode *inode, struct file *flip,
                 ret = -EFAULT;  
             }
             break;
-    
+
+//swda add,02/04/2005
+               case BOARD_IOCTL_GET_SERIAL_NUMBER:
+                       if(copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) {
+                               strncpy(ctrlParms.string, g_Serial_No, SN_SIZE);
+                               ctrlParms.strLen = SN_SIZE;
+                               ctrlParms.string[ctrlParms.strLen] = '\0';
+                               ctrlParms.result = 0;
+                               __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));
+                               ret = 0;                        
+                       } else {
+                               ret = -EFAULT;
+                       }
+                       break;          
+
+#ifdef DEFAULT_WLAN_WEP128
+               case BOARD_IOCTL_GET_WEP128_KEY:
+                       if(copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) {
+                               strncpy(ctrlParms.string, g_WEP128bit_key,WEP128KEY_SIZE);
+                               ctrlParms.strLen = WEP128KEY_SIZE;
+                               ctrlParms.string[ctrlParms.strLen] = '\0';
+                               ctrlParms.result = 0;
+                               __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));
+                               ret = 0;                        
+                       } else {
+                               ret = -EFAULT;
+                       }
+                       break;
+#endif
+
+               case BOARD_IOCTL_INFO_BOOT_COMPLETE:
+                       printk("board_ioctl: boot complete!\n");
+                       boot_complete_flag = 1;
+                       break;
+
+#ifdef LLL_TEST_LED
+               case BOARD_IOCTL_SET_LLL_TEST_LED:
+                       if(copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) {
+                               if (ctrlParms.offset==0) {
+                                       LLLTestLedTimerDelete();//if timer already running, delete it
+                                       kerSysLedCtrl( kLedPPP, kLedStateOff );
+                               } else if (ctrlParms.offset==1) {
+                                       LLLTestLedTimerDelete();//if timer already running, delete it
+                                       kerSysLedCtrl( kLedPPP, kLedStateOn );
+                                       LLLTestLedTimerStart();//turn off LLL test led after 30 seconds
+                               } else if (ctrlParms.offset==2) {
+                                       LLLTestLedTimerDelete();//if timer already running, delete it
+                                       kerSysLedCtrl( kLedPPP, kLedStateFastBlinkContinues );
+                                       LLLTestLedTimerStart();//turn off LLL test led after 30 seconds
+                               }
+                               ctrlParms.result = 0;
+                               ret = 0;                        
+                       } else {
+                               ret = -EFAULT;
+                       }
+                       break;
+#endif
+#if VOXXXLOAD
+               case BOARD_IOCTL_PSTNCALL:
+                       spin_lock(&pstn_spin_lock);
+                       ctrlParms.result = (int) PSTNComingCall;
+                       spin_unlock(&pstn_spin_lock);
+                       __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));
+                       ret=0;
+                       break;
+               case BOARD_IOCTL_OFFHOOK:
+                       spin_lock(&offhook_spin_lock);
+                       ctrlParms.result = (int) PSTNphone2OFFHOOK;
+                       spin_unlock(&offhook_spin_lock);
+                       __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));
+                       ret = 0;
+                       break;
+#endif
+#if ODM_AUTO_PROVISION_LAN
+               case BOARD_IOCTL_AUTO_PROVISION_LAN:
+                       ctrlParms.result = (int) autoprovisionlan;
+                       __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));
+                       ret = 0;
+                       break;
+#endif
+
+#ifdef WLAN_ENABLE_CTRL_BUTTON
+               case BOARD_IOCTL_WLAN_ENABLE_CTRL_BUTTON:
+                       if(copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) {
+                               if ( ctrlParms.strLen == GET_BOOT_COMPLETE_FLAG ) {
+                                       ctrlParms.result = boot_complete_flag;
+                               } else if ( ctrlParms.strLen == GET_WLAN_ENABLE_GPIO_STATUS ) {
+                                       ctrlParms.result = (GPIO->GPIOio & (unsigned int)GPIO_WLAN_ENABLE_STATE) ? 1 : 0;
+                               }
+                               
+                               __copy_to_user((BOARD_IOCTL_PARMS*)arg, &ctrlParms, sizeof(BOARD_IOCTL_PARMS));
+                               ret = 0;                        
+                       } else {
+                               ret = -EFAULT;
+                       }
+                       break;
+#endif
+//swda add end    
+//swda add,11/29/2006
+               case BOARD_IOCTL_SET_VAR:
+                       if(copy_from_user((void*)&ctrlParms, (void*)arg, sizeof(ctrlParms)) == 0) {
+                               if ( strcmp(ctrlParms.string,"MultiConfig")==0 ) {
+                                       IsMultiConfig = ctrlParms.strLen;
+                               }
+                               ctrlParms.result = 0;
+                               ret = 0;                        
+                       } else {
+                               ret = -EFAULT;
+                       }
+                       break;
+//swda add end
         default:
             ret = -EINVAL;
             ctrlParms.result = 0;
@@ -1655,12 +2514,23 @@ static unsigned int kerSysDyingGaspIsr(void)
     CB_DGASP_LIST *tmp = NULL, *dsl = NULL;    
 
     if (kerSysDyingGaspCheckPowerLoss()) {        
-
+#ifdef POWER_SAVING_DG
+               GPIO->GPIODir_high |= GPIO_NUM_TO_MASK_HIGH(35);//set GPIO 35 as output
+               GPIO->GPIOio_high &= (~GPIO_NUM_TO_MASK_HIGH(35));//pull GPIO 35 low to reset 5325 ethernet switch
+               GPIO->GPIODir_high |= GPIO_NUM_TO_MASK_HIGH(36);//set GPIO 36 as output
+               GPIO->GPIOio_high &= (~GPIO_NUM_TO_MASK_HIGH(36));//pull GPIO 36 low to reset dsp 6341
+               //printk("GPIO->GPIODir_high=0x%X\n",GPIO->GPIODir_high);
+               //printk("GPIO->GPIOio_high=0x%X\n",GPIO->GPIOio_high);
+#endif
         /* 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)) {
+#if POWER_SAVING_DG  //michaelc CSP#41165 patch 
                (tmp->cb_dgasp_fn)(tmp->context); 
+#else
+                ;
+#endif
            }else {
                dsl = tmp;                      
            }       
@@ -1669,7 +2539,7 @@ static unsigned int kerSysDyingGaspIsr(void)
         /* now send dgasp */
         if(dsl)
             (dsl->cb_dgasp_fn)(dsl->context); 
-
+#if POWER_SAVING_DG    //swda mark,06/15/2006
         /* reset and shutdown system */
         kerSysDyingGaspShutdown();
 
@@ -1677,6 +2547,7 @@ static unsigned int kerSysDyingGaspIsr(void)
 
         while (1)
             ;
+#endif
     }
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
 return( IRQ_HANDLED );
@@ -1849,6 +2720,53 @@ static irqreturn_t reset_isr(int irq, void *dev_id, struct pt_regs *ptregs)
 }
 
 
+//swda add,05/10/2006
+#ifdef BACKUP_WLAN_SPROM
+void kerSysGetSpromSavedFlag(unsigned char *pspromsavedflag)
+{
+        //PNVRAM_DATA pNvramData = (PNVRAM_DATA) get_nvram_start_addr();
+        //*pspromsavedflag = pNvramData->sprom_saved_flag;
+        //srom save flag has been read in InitNvramInfo
+        *pspromsavedflag = g_SROMSaveFlag;
+}
+void kerSysSetSpromSavedFlag(unsigned char spromsavedflag)
+{
+        PNVRAM_DATA pNvramData = (PNVRAM_DATA) get_nvram_start_addr();
+        NVRAM_DATA SaveNvramData;
+        UINT32 crc = CRC32_INIT_VALUE;
+    
+        // save NVRAM data into a local structure
+     memcpy( &SaveNvramData, pNvramData, sizeof(NVRAM_DATA) );
+     SaveNvramData.sprom_saved_flag = spromsavedflag;
+     
+     //write the nvramData struct to nvram after CRC is calculated
+     SaveNvramData.ulCheckSum = 0;
+     crc = getCrc32((char *)&SaveNvramData, (UINT32) sizeof(NVRAM_DATA), crc);      
+     SaveNvramData.ulCheckSum = crc;
+     kerSysNvRamSet((char *) &SaveNvramData, sizeof(SaveNvramData), 0);
+}
+void kerSysGetSpromTable(char *pspromdata,int size,int offset)
+{
+     //kerSysNvRamGet(pspromdata, size, offset);
+     //SPROM has been read in InitNvramInfo
+     memcpy(pspromdata,g_SPROMData,NVRAM_SPROM_TABLE_SIZE);
+}
+void kerSysSetSpromTable(char *pspromdata,int size,int offset)
+{
+     kerSysNvRamSet(pspromdata, size, offset);
+}
+#endif //BACKUP_WLAN_SPROM
+
+int kerSysSetUpgradeState(int state)
+{
+       is_update_flash = state;
+}
+int kerSysGetUpgradeState(void)
+{
+       return is_update_flash;
+}
+//swda add end
+
 /***************************************************************************
  * MACRO to call driver initialization and cleanup functions.
  ***************************************************************************/
@@ -1894,3 +2812,10 @@ EXPORT_SYMBOL(kerSysDeregisterDyingGaspHandler);
 EXPORT_SYMBOL(kerSysGetCycleCount);
 EXPORT_SYMBOL(kerSysSetWdTimer);
 EXPORT_SYMBOL(kerSysWakeupMonitorTask);
+#ifdef BACKUP_WLAN_SPROM
+EXPORT_SYMBOL(kerSysGetSpromSavedFlag);
+EXPORT_SYMBOL(kerSysSetSpromSavedFlag);
+EXPORT_SYMBOL(kerSysGetSpromTable);
+EXPORT_SYMBOL(kerSysSetSpromTable);
+#endif
+EXPORT_SYMBOL(kerSysGetUpgradeState);//swda add,06/27/2006