http://downloads.netgear.com/files/GPL/GPL_Source_V361j_DM111PSP_series_consumer_rele...
[bcm963xx.git] / bcmdrivers / opensource / char / board / bcm963xx / impl1 / bcm63xx_flash.c
1 /*
2 <:copyright-gpl
3  Copyright 2002 Broadcom Corp. All Rights Reserved.
4
5  This program is free software; you can distribute it and/or modify it
6  under the terms of the GNU General Public License (Version 2) as
7  published by the Free Software Foundation.
8
9  This program is distributed in the hope it will be useful, but WITHOUT
10  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  for more details.
13
14  You should have received a copy of the GNU General Public License along
15  with this program; if not, write to the Free Software Foundation, Inc.,
16  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
17 :>
18 */
19 /*
20  ***************************************************************************
21  * File Name  : bcm63xx_flash.c
22  *
23  * Description: This file contains the flash device driver APIs for bcm63xx board. 
24  *
25  * Created on :  8/10/2002  seanl:  use cfiflash.c, cfliflash.h (AMD specific)
26  *
27  ***************************************************************************/
28
29
30 /* Includes. */
31 #include <linux/fs.h>
32 #include <linux/capability.h>
33 #include <linux/slab.h>
34 #include <linux/errno.h>
35 #include <linux/module.h>
36 #include <linux/interrupt.h>
37 #include <asm/uaccess.h>
38
39 #include <bcm_map_part.h>
40 #include <board.h>
41 #define  BCMTAG_EXE_USE
42 #include <bcmTag.h>
43 #include "flash_api.h"
44 #include "boardparms.h"
45
46 //#define DEBUG_FLASH
47
48 extern PFILE_TAG kerSysImageTagGet(void);
49
50 static FLASH_ADDR_INFO fInfo;
51 static int flashInitialized = 0;
52
53 /*Michael: for fix crash when push reset button */
54 void *retriedKmallocRESET(size_t size)
55 {
56         void *pBuf;
57     int tryCount = 0;
58
59     // try 1000 times before quit
60 /*Michael: for fix crash when push reset button */
61 /* if we kill pppd and do reset button push, it goes fine. This method provided by viclin */
62 //    while (((pBuf = kmalloc(size, GFP_KERNEL)) == NULL) && (tryCount++ < 1000)){
63     while (((pBuf = kmalloc(size, GFP_ATOMIC)) == NULL) && (tryCount++ < 1000)){
64                 current->state   = TASK_INTERRUPTIBLE;
65                 schedule_timeout(HZ/10);
66         }
67     if (tryCount >= 1000)
68         pBuf = NULL;
69     else
70         memset(pBuf, 0, size);
71
72     return pBuf;
73 }
74
75
76 void *retriedKmalloc(size_t size)
77 {
78         void *pBuf;
79     int tryCount = 0;
80     int allocType = GFP_KERNEL;
81
82     if( in_interrupt() )
83     {
84         allocType = GFP_ATOMIC;
85         tryCount = 999;
86     }
87
88     // try 1000 times before quit
89     while (((pBuf = kmalloc(size, allocType)) == NULL) && (++tryCount < 1000))
90     {
91                 current->state   = TASK_INTERRUPTIBLE;
92                 schedule_timeout(HZ/10);
93         }
94     if (tryCount >= 1000)
95         pBuf = NULL;
96     else
97             memset(pBuf, 0, size);
98
99     return pBuf;
100 }
101
102 void retriedKfree(void *pBuf)
103 {
104         kfree(pBuf);
105 }
106
107 /***************************************************************************
108 // Function Name: getCrc32
109 // Description  : caculate the CRC 32 of the given data.
110 // Parameters   : pdata - array of data.
111 //                size - number of input data bytes.
112 //                crc - either CRC32_INIT_VALUE or previous return value.
113 // Returns      : crc.
114 ****************************************************************************/
115 UINT32 getCrc32(byte *pdata, UINT32 size, UINT32 crc) 
116 {
117     while (size-- > 0)
118         crc = (crc >> 8) ^ Crc32_table[(crc ^ *pdata++) & 0xff];
119
120     return crc;
121 }
122
123 // get the nvram start addr
124 //
125 unsigned long get_nvram_start_addr(void)
126 {
127     return ((unsigned long) 
128         (flash_get_memptr(fInfo.flash_nvram_start_blk) + fInfo.flash_nvram_blk_offset));
129 }
130
131 // get the scratch_pad start addr
132 //
133 unsigned long get_scratch_pad_start_addr(void)
134 {
135     return ((unsigned long) 
136         (flash_get_memptr(fInfo.flash_scratch_pad_start_blk) + fInfo.flash_scratch_pad_blk_offset));
137 }
138
139
140 #if defined(CONFIG_BCM96348)  
141 /*  *********************************************************************
142     *  kerSysImageTagGet()
143     *   Get the image tag
144     *  Input parameters:
145     *      none
146     *  Return value:
147     *      point to tag -- Found
148     *      NULL -- failed
149     ********************************************************************* */
150 PFILE_TAG kerSysImageTagGet(void)
151 {
152     int i,startblock;
153     int totalBlks = flash_get_numsectors();
154     int totalSize = flash_get_total_size();
155     UINT32 crc;
156     unsigned char *sectAddr;
157     PFILE_TAG pTag;
158     unsigned char   nbootflag,*bootflag;
159
160     bootflag=flash_get_memptr((byte) 0);
161     
162     if (totalSize == 0x800000) {nbootflag=*bootflag;}
163     else nbootflag=1;
164     
165     if (nbootflag == 2) nbootflag = 0; /*binfs is valid to boot from bfc00000*/
166     startblock = (nbootflag?1:(totalBlks>>1)+1);
167 #if defined(DEBUG_FLASH)
168     printk("totalblks in tagGet=%d\n", totalBlks);
169 #endif
170
171
172     // start blk, assume 1st one is always CFE
173     for (i = startblock; i < startblock + (totalBlks>>1); i++)
174     {
175         sectAddr =  flash_get_memptr((byte) i);
176         crc = CRC32_INIT_VALUE;
177         crc = getCrc32(sectAddr, (UINT32)TAG_LEN-TOKEN_LEN, crc);      
178         pTag = (PFILE_TAG) sectAddr;
179
180 #if defined(DEBUG_FLASH)
181         printk("Check Tag crc on blk [%d]\n", i);
182 #endif
183
184         if (crc == (UINT32)(*(UINT32*)(pTag->tagValidationToken)))
185             return pTag;
186     }
187
188     return (PFILE_TAG) NULL;
189 }
190
191 PFILE_TAG kerSysImageTagGet2(void)
192 {
193     int i,startblock;
194     int totalBlks = flash_get_numsectors();
195     int totalSize = flash_get_total_size();
196     UINT32 crc;
197     unsigned char *sectAddr;
198     PFILE_TAG pTag;
199     unsigned char   nbootflag,*bootflag;
200
201     bootflag=flash_get_memptr((byte) 0);
202     
203     if (totalSize == 0x800000)  nbootflag=1; /*always get from bf800000 */
204     else return (PFILE_TAG) NULL;
205     
206     startblock = (nbootflag?1:(totalBlks>>1)+1);
207 #if defined(DEBUG_FLASH)
208     printk("totalblks in tagGet=%d\n", totalBlks);
209 #endif
210
211
212     // start blk, assume 1st one is always CFE
213     for (i = startblock; i < startblock + (totalBlks>>1); i++)
214     {
215         sectAddr =  flash_get_memptr((byte) i);
216         crc = CRC32_INIT_VALUE;
217         crc = getCrc32(sectAddr, (UINT32)TAG_LEN-TOKEN_LEN, crc);      
218         pTag = (PFILE_TAG) sectAddr;
219
220         if (*((unsigned char*) pTag->kernelLen) == 0x30 ) {
221                 
222 #if defined(DEBUG_FLASH)
223         printk("Check Tag crc on blk [%d]\n", i);
224 #endif
225
226             if (crc == (UINT32)(*(UINT32*)(pTag->tagValidationToken)))
227                 return pTag;
228         }
229     }
230
231     return  (PFILE_TAG) NULL;
232 }
233
234
235 #endif
236
237 #if defined(CONFIG_BCM96338)
238 PFILE_TAG kerSysImageTagGet(void)
239 {
240     int i,startblock;
241     int totalBlks = flash_get_numsectors();
242     int totalSize = flash_get_total_size();
243     UINT32 crc;
244     unsigned char *sectAddr;
245     PFILE_TAG pTag;
246     unsigned char bootf1,bootf2,nbootflag=0;
247
248     
249 if (totalSize == 0x400000) {
250     bootf1 = *(unsigned char*) (0xbfe00000 -1); /*see design note 4MB flash layout*/
251     bootf2 = *(unsigned char*) (0xbfff0000 -1);
252     if ((bootf1 >> 2) == 0 && bootf1 ) {
253         if ((bootf2 >> 2) == 0 && bootf2 ) { /* both are valid */
254           if ((bootf1+1) == bootf2 || ((bootf1+1) >>2 == bootf2) ) nbootflag=1; /*bank2*/
255           if ((bootf2+1) == bootf1 || ((bootf2+1) >>2 == bootf1) ) nbootflag=0; /*bank1*/ 
256         } else nbootflag = 0; /* bank2 invalid bank1 valid */
257     }
258     else  if ((bootf2 >> 2) == 0 && bootf2) nbootflag =1; /*bank 1 invalid,bank 2 valid*/
259     else  nbootflag=0; /* bank1 bank2 both invalid */
260     
261     printk("bootf1=%x bootf2=%x\n", bootf1,bootf2);
262 }
263 else nbootflag=0; 
264     
265     startblock = nbootflag?flash_get_blk(0xbfe00000):1;
266 #if defined(DEBUG_FLASH)
267     printk("totalblks in tagGet=%d\n", totalBlks);
268 #endif
269
270
271     // start blk, assume 1st one is always CFE
272     for (i = startblock; i < startblock + (totalBlks>>1); i++)
273     {
274         sectAddr =  flash_get_memptr((byte) i);
275         crc = CRC32_INIT_VALUE;
276         crc = getCrc32(sectAddr, (UINT32)TAG_LEN-TOKEN_LEN, crc);      
277         pTag = (PFILE_TAG) sectAddr;
278
279 #if defined(DEBUG_FLASH)
280         printk("Check Tag crc on blk [%d]\n", i);
281 #endif
282
283         if (crc == (UINT32)(*(UINT32*)(pTag->tagValidationToken)))
284             return pTag;
285     }
286
287     return (PFILE_TAG) NULL;    
288 }  
289 #endif
290 // Initialize the flash and fill out the fInfo structure
291 void kerSysFlashInit( void )
292 {
293     int i = 0;
294     int totalBlks = 0;
295     int totalSize = 0;
296     int startAddr = 0;
297     int usedBlkSize = 0;
298     NVRAM_DATA nvramData;
299     UINT32 crc = CRC32_INIT_VALUE, savedCrc;
300     PFILE_TAG pTag = NULL;
301     unsigned long kernelEndAddr = 0;
302     unsigned long spAddr = 0;
303
304     if (flashInitialized)
305         return;
306
307     flashInitialized = 1;
308     flash_init();
309
310     totalBlks = flash_get_numsectors();
311     totalSize = flash_get_total_size();
312
313     printk("Total Flash size: %dK with %d sectors\n", totalSize/1024, totalBlks);
314
315     /* nvram is always at the end of flash */
316     fInfo.flash_nvram_length = NVRAM_LENGTH;
317   printk("FLASH_BASE %x,blk %d\n",FLASH_BASE,flash_get_blk(FLASH_BASE));
318     fInfo.flash_nvram_start_blk = flash_get_blk(FLASH_BASE);    /* denny 09/13/04' modified, set the nvram locate at boot loader sector */
319     fInfo.flash_nvram_number_blk = 1; /*always fits in the first block */
320     fInfo.flash_nvram_blk_offset = NVRAM_DATA_OFFSET;
321  
322     // check nvram CRC
323     memcpy((char *)&nvramData, (char *)get_nvram_start_addr(), sizeof(NVRAM_DATA));
324     savedCrc = nvramData.ulCheckSum;
325     nvramData.ulCheckSum = 0;
326     crc = getCrc32((char *)&nvramData, (UINT32) sizeof(NVRAM_DATA), crc);   
327
328     BpSetBoardId( nvramData.szBoardId );
329
330     fInfo.flash_persistent_length = NVRAM_PSI_DEFAULT;
331     if (savedCrc != crc)
332     {
333         printk("***Board is not initialized****: Using the default PSI size: %d\n",
334             fInfo.flash_persistent_length);
335     }
336     else
337     {
338         unsigned long ulPsiSize;
339         if( BpGetPsiSize( &ulPsiSize ) == BP_SUCCESS )
340             fInfo.flash_persistent_length = ulPsiSize;
341         else
342         {
343             printk("***Board id is not set****: Using the default PSI size: %d\n",
344                 fInfo.flash_persistent_length);
345         }
346     }
347
348     fInfo.flash_persistent_length *= ONEK;
349     startAddr = totalSize - fInfo.flash_persistent_length;
350 #if defined (CONFIG_BCM96348) || defined(CONFIG_BCM96338)       
351     fInfo.flash_persistent_start_blk = flash_get_blk(startAddr+get_flash_base(0));
352 #endif
353 #if defined (CONFIG_BCM96358)
354     fInfo.flash_persistent_start_blk = flash_get_blk(startAddr+FLASH_BASE);
355 #endif
356     fInfo.flash_persistent_number_blk = totalBlks - fInfo.flash_persistent_start_blk;
357     // save abs SP address (Scratch Pad). it is before PSI 
358     spAddr = startAddr - SP_MAX_LEN ;
359     // find out the offset in the start_blk
360     usedBlkSize = 0;
361     for (i = fInfo.flash_persistent_start_blk; 
362         i < (fInfo.flash_persistent_start_blk + fInfo.flash_persistent_number_blk); i++)
363     {
364         usedBlkSize += flash_get_sector_size( i);
365     }
366     fInfo.flash_persistent_blk_offset =  usedBlkSize - fInfo.flash_persistent_length;
367
368     // get the info for sp
369     if (!(pTag = kerSysImageTagGet()))
370     {
371         printk("Failed to read image tag from flash\n");
372         return;
373     }
374     kernelEndAddr = (unsigned long)simple_strtoul(pTag->kernelAddress,NULL,10)+ \
375         (unsigned long) simple_strtoul(pTag->kernelLen, NULL, 10) + BOOT_OFFSET;
376
377
378 #if defined (CONFIG_BCM96348) || defined(CONFIG_BCM96338)
379     fInfo.flash_scratch_pad_start_blk = flash_get_blk(spAddr+get_flash_base(0));
380 #endif
381
382 #if defined (CONFIG_BCM96358)
383     // make suer sp does not share kernel block
384     fInfo.flash_scratch_pad_start_blk = flash_get_blk(spAddr+FLASH_BASE);
385 #endif
386     if (fInfo.flash_scratch_pad_start_blk != flash_get_blk(kernelEndAddr))
387     {
388         fInfo.flash_scratch_pad_length = SP_MAX_LEN;
389         if (fInfo.flash_persistent_start_blk == fInfo.flash_scratch_pad_start_blk)  // share blk
390         {
391 #if 0 /* do not used scratch pad unless it's in its own sector */
392             printk("Scratch pad is not used for this flash part.\n");  
393             fInfo.flash_scratch_pad_length = 0;     // no sp
394 #else /* allow scratch pad to share a sector with another section such as PSI */
395             fInfo.flash_scratch_pad_number_blk = 1;
396             fInfo.flash_scratch_pad_blk_offset = fInfo.flash_persistent_blk_offset - fInfo.flash_scratch_pad_length;
397 #endif
398         }
399         else // on different blk
400         {
401             fInfo.flash_scratch_pad_number_blk = fInfo.flash_persistent_start_blk\
402                 - fInfo.flash_scratch_pad_start_blk;
403             // find out the offset in the start_blk
404             usedBlkSize = 0;
405             for (i = fInfo.flash_scratch_pad_start_blk; 
406                 i < (fInfo.flash_scratch_pad_start_blk + fInfo.flash_scratch_pad_number_blk); i++)
407                 usedBlkSize += flash_get_sector_size(i);
408                 fInfo.flash_scratch_pad_blk_offset =  usedBlkSize - fInfo.flash_scratch_pad_length;
409         }
410     }
411     else
412     {
413         printk("No flash for scratch pad!\n");  
414         fInfo.flash_scratch_pad_length = 0;     // no sp
415     }
416
417     /*==== add by Andrew (2004/09/14) ====*/
418 #if defined(CFG_XFER_TO_FACDEFLT)
419     // save abs factdeflt address (Factory Default). it is before SP
420     unsigned long dfAddr;
421
422         if(fInfo.flash_scratch_pad_length>0) {
423         dfAddr = spAddr - NVRAM_PSI_DEFAULT*ONEK;
424         // make sure factdeflt does not share kernel block
425 #if defined (CONFIG_BCM96348) || defined(CONFIG_BCM96338)
426         fInfo.flash_factdeflt_start_blk = flash_get_blk(dfAddr+get_flash_base(0));
427 #endif
428 #if defined (CONFIG_BCM96358)
429                 fInfo.flash_factdeflt_start_blk = flash_get_blk(dfAddr+FLASH_BASE);
430 #endif
431         if (fInfo.flash_factdeflt_start_blk != flash_get_blk(kernelEndAddr)) {
432             fInfo.flash_factdeflt_length = NVRAM_PSI_DEFAULT*ONEK;
433             if (fInfo.flash_factdeflt_start_blk == fInfo.flash_scratch_pad_start_blk)  // share blk
434             {
435                 fInfo.flash_factdeflt_number_blk = 1;
436                 fInfo.flash_factdeflt_blk_offset = fInfo.flash_scratch_pad_blk_offset - fInfo.flash_factdeflt_length;
437             } else { // on different blk
438                 fInfo.flash_factdeflt_number_blk = fInfo.flash_scratch_pad_start_blk - fInfo.flash_factdeflt_start_blk;
439                 // find out the offset in the start_blk
440                 usedBlkSize = 0;
441                 for (i = fInfo.flash_factdeflt_start_blk; 
442                     i < (fInfo.flash_factdeflt_start_blk + fInfo.flash_factdeflt_number_blk); i++)
443                     usedBlkSize += flash_get_sector_size( i);
444                 fInfo.flash_factdeflt_blk_offset =  usedBlkSize - fInfo.flash_factdeflt_length;
445             }
446         } else {
447             printk("Not enough flash space to store factory default setting!\n");  
448             fInfo.flash_factdeflt_length = 0;     // no df
449         }
450     } else {
451             dfAddr = startAddr - NVRAM_PSI_DEFAULT*ONEK;
452         // make sure factdeflt does not share kernel block
453 #if defined (CONFIG_BCM96348) || defined(CONFIG_BCM96338)
454         fInfo.flash_factdeflt_start_blk = flash_get_blk(dfAddr+get_flash_base(0));
455 #endif
456 #if defined (CONFIG_BCM96358)
457                 fInfo.flash_factdeflt_start_blk = flash_get_blk(dfAddr+FLASH_BASE);
458 #endif
459         if (fInfo.flash_factdeflt_start_blk != flash_get_blk(kernelEndAddr)) {
460             fInfo.flash_factdeflt_length = NVRAM_PSI_DEFAULT*ONEK;
461             if (fInfo.flash_factdeflt_start_blk == fInfo.flash_persistent_start_blk)  // share blk
462             {
463                 fInfo.flash_factdeflt_number_blk = 1;
464                 fInfo.flash_factdeflt_blk_offset = fInfo.flash_persistent_blk_offset - fInfo.flash_factdeflt_length;
465             } else { // on different blk
466                 fInfo.flash_factdeflt_number_blk = fInfo.flash_persistent_start_blk - fInfo.flash_factdeflt_start_blk;
467                 // find out the offset in the start_blk
468                 usedBlkSize = 0;
469                 for (i = fInfo.flash_factdeflt_start_blk; 
470                     i < (fInfo.flash_factdeflt_start_blk + fInfo.flash_factdeflt_number_blk); i++)
471                     usedBlkSize += flash_get_sector_size( i);
472                 fInfo.flash_factdeflt_blk_offset =  usedBlkSize - fInfo.flash_factdeflt_length;
473             }
474         } else {
475             printk("Not enough flash space to store factory default setting!\n");  
476             fInfo.flash_factdeflt_length = 0;     // no df
477         }
478     }
479 #endif
480     /*==== end ====*/
481 #if defined(DEBUG_FLASH)
482   #if defined(CFG_XFER_TO_FACDEFLT)
483 #if defined (CONFIG_BCM96348) || defined(CONFIG_BCM96338)
484     printk("dfAddr = %x\n", dfAddr+get_flash_base(0));
485 #endif
486 #if defined (CONFIG_BCM96358)
487         printk("dfAddr = %x\n", dfAddr+FLASH_BASE);
488 #endif
489     printk("fInfo.flash_factdeflt_start_blk = %d\n", fInfo.flash_factdeflt_start_blk);
490     printk("fInfo.flash_factdeflt_number_blk = %d\n", fInfo.flash_factdeflt_number_blk);
491     printk("fInfo.flash_factdeflt_length = 0x%x\n", fInfo.flash_factdeflt_length);
492     printk("fInfo.flash_factdeflt_blk_offset = 0x%x\n", (unsigned int)fInfo.flash_factdeflt_blk_offset);
493   #endif
494     printk("fInfo.flash_scratch_pad_start_blk = %d\n", fInfo.flash_scratch_pad_start_blk);
495     printk("fInfo.flash_scratch_pad_number_blk = %d\n", fInfo.flash_scratch_pad_number_blk);
496     printk("fInfo.flash_scratch_pad_length = 0x%x\n", fInfo.flash_scratch_pad_length);
497     printk("fInfo.flash_scratch_pad_blk_offset = 0x%x\n", (unsigned int)fInfo.flash_scratch_pad_blk_offset);
498
499     printk("fInfo.flash_nvram_start_blk = %d\n", fInfo.flash_nvram_start_blk);
500     printk("fInfo.flash_nvram_blk_offset = 0x%x\n", (unsigned int)fInfo.flash_nvram_blk_offset);
501     printk("fInfo.flash_nvram_number_blk = %d\n", fInfo.flash_nvram_number_blk);
502 #if defined (CONFIG_BCM96348) || defined(CONFIG_BCM96338)
503     printk("psi startAddr = %x\n", startAddr+get_flash_base(0));
504 #endif
505 #if defined (CONFIG_BCM96358)
506     printk("psi startAddr = %x\n", startAddr+FLASH_BASE);
507 #endif
508     printk("fInfo.flash_persistent_start_blk = %d\n", fInfo.flash_persistent_start_blk);
509     printk("fInfo.flash_persistent_blk_offset = 0x%x\n", (unsigned int)fInfo.flash_persistent_blk_offset);
510     printk("fInfo.flash_persistent_number_blk = %d\n", fInfo.flash_persistent_number_blk);
511 #endif
512
513 }
514
515
516
517 /***********************************************************************
518  * Function Name: kerSysFlashAddrInfoGet
519  * Description  : Fills in a structure with information about the NVRAM
520  *                and persistent storage sections of flash memory.  
521  *                Fro physmap.c to mount the fs vol.
522  * Returns      : None.
523  ***********************************************************************/
524 void kerSysFlashAddrInfoGet(PFLASH_ADDR_INFO pflash_addr_info)
525 {
526     pflash_addr_info->flash_nvram_blk_offset = fInfo.flash_nvram_blk_offset;
527     pflash_addr_info->flash_nvram_length = fInfo.flash_nvram_length;
528     pflash_addr_info->flash_nvram_number_blk = fInfo.flash_nvram_number_blk;
529     pflash_addr_info->flash_nvram_start_blk = fInfo.flash_nvram_start_blk;
530     pflash_addr_info->flash_persistent_blk_offset = fInfo.flash_persistent_blk_offset;
531     pflash_addr_info->flash_persistent_length = fInfo.flash_persistent_length;
532     pflash_addr_info->flash_persistent_number_blk = fInfo.flash_persistent_number_blk;
533     pflash_addr_info->flash_persistent_start_blk = fInfo.flash_persistent_start_blk;
534 }
535
536
537 // get shared blks into *** pTempBuf *** which has to be released bye the caller!
538 // return: if pTempBuf != NULL, poits to the data with the dataSize of the buffer
539 // !NULL -- ok
540 // NULL  -- fail
541 static char *getSharedBlks(int start_blk, int end_blk)
542 {
543     int i = 0;
544     int usedBlkSize = 0;
545     int sect_size = 0;
546     char *pTempBuf = NULL;
547     char *pBuf = NULL;
548
549     for (i = start_blk; i < end_blk; i++)
550         usedBlkSize += flash_get_sector_size( i);
551
552 #if defined(DEBUG_FLASH)
553     printk("usedBlkSize = %d\n", usedBlkSize);
554 #endif
555
556     if ((pTempBuf = (char *) retriedKmalloc(usedBlkSize)) == NULL)
557     {
558         printk("failed to allocate memory with size: %d\n", usedBlkSize);
559         return pTempBuf;
560     }
561     
562     pBuf = pTempBuf;
563     for (i = start_blk; i < end_blk; i++)
564     {
565         sect_size = flash_get_sector_size( i);
566
567 #if defined(DEBUG_FLASH)
568         printk("i = %d, sect_size = %d, end_blk = %d\n", i, sect_size, end_blk);
569 #endif
570         flash_read_buf(i, 0, pBuf, sect_size);
571         pBuf += sect_size;
572     }
573     
574     return pTempBuf;
575 }
576
577 /*Michael: for fix crash when push reset button */
578 /* We add this because it happen only at 2Mflash 8M SDRAM. */
579 static char *getSharedBlksRESET(int start_blk, int end_blk)
580 {
581     int i = 0;
582     int usedBlkSize = 0;
583     int sect_size = 0;
584     char *pTempBuf = NULL;
585     char *pBuf = NULL;
586
587     for (i = start_blk; i < end_blk; i++)
588         usedBlkSize += flash_get_sector_size( i);
589
590 #if defined(DEBUG_FLASH)
591     printk("usedBlkSize = %d\n", usedBlkSize);
592 #endif
593     
594     if ((pTempBuf = (char *) retriedKmallocRESET(usedBlkSize)) == NULL)
595     {
596         printk("failed to allocate memory with size: %d\n", usedBlkSize);
597     return pTempBuf;
598     }
599
600     pBuf = pTempBuf;
601     for (i = start_blk; i < end_blk; i++)
602     {
603         sect_size = flash_get_sector_size( i);
604 #if defined(DEBUG_FLASH)
605         printk("i = %d, sect_size = %d, end_blk = %d\n", i, sect_size, end_blk);
606 #endif
607         flash_read_buf(i, 0, pBuf, sect_size);
608         pBuf += sect_size;
609     }
610     return pTempBuf;
611 }
612
613
614 // Set the pTempBuf to flash from start_blk to end_blk
615 // return:
616 // 0 -- ok
617 // -1 -- fail
618 static int setSharedBlks(int start_blk, int end_blk, char *pTempBuf)
619 {
620     int i = 0;
621     int sect_size = 0;
622     int sts = 0;
623     char *pBuf = pTempBuf;
624
625     for (i = start_blk; i < end_blk; i++)
626     {
627         sect_size = flash_get_sector_size( i);
628         flash_sector_erase_int(i);
629         if (flash_write_buf(i, 0, pBuf, sect_size) != sect_size)
630         {
631             printk("Error writing flash sector %d.", i);
632             sts = -1;
633             break;
634         }
635         pBuf += sect_size;
636     }
637
638     return sts;
639 }
640
641
642
643 /*******************************************************************************
644  * NVRAM functions
645  *******************************************************************************/
646
647 // get nvram data
648 // return:
649 //  0 - ok
650 //  -1 - fail
651 int kerSysNvRamGet(char *string, int strLen, int offset)
652 {
653     char *pBuf = NULL;
654
655     if (!flashInitialized)
656         kerSysFlashInit();
657
658     if (strLen > NVRAM_LENGTH)
659         return -1;
660
661     if ((pBuf = getSharedBlks(fInfo.flash_nvram_start_blk,
662         (fInfo.flash_nvram_start_blk + fInfo.flash_nvram_number_blk))) == NULL)
663         return -1;
664
665     // get string off the memory buffer
666     memcpy(string, (pBuf + fInfo.flash_nvram_blk_offset + offset), strLen);
667
668     retriedKfree(pBuf);
669
670     return 0;
671 }
672
673 #if defined(CONFIG_BCM96348) 
674 int kerSysErasePS1()
675 {
676         int i,j;
677         i=j=0;
678         
679          do {
680          i+=flash_get_sector_size(j);
681          j++;
682         } while (i<64*1024);
683         
684         flash_sector_erase_int(j);
685
686         
687 }
688 int kerSysBootFlagSet(char bootflag)
689 {
690     int i = 0;
691     int sect_size = 0;
692     int sts = 0;
693     char *pTempBuf = NULL;
694     
695        printk("set bootflag %d\n",bootflag);
696         sect_size = flash_get_sector_size(0);   /* denny 09/13/04' modified */
697         if ((pTempBuf = (char *) retriedKmalloc(sect_size)) == NULL) {
698             printk("failed to allocate memory with size: %d\n", sect_size);
699             return -1;
700         
701         }        
702         flash_read_buf(0, 0, pTempBuf, sect_size);      
703         flash_sector_erase_int(0);
704         *((char *) pTempBuf) = bootflag;
705         if (flash_write_buf(0, 0, pTempBuf, sect_size) != sect_size)
706         {
707             printk("Error writing flash sector %d.\n", i);
708             sts = -1;
709         }
710         retriedKfree(pTempBuf); 
711         return sts;
712 }
713 #endif
714
715 #if defined(CONFIG_BCM96338) || defined(CONFIG_BCM96358)
716 int kerSysErasePS1()
717 {
718         int j;
719 #if defined(CONFIG_BCM96338)    
720     if (flash_get_total_size() == 0x400000) {
721         j=flash_get_blk(0xbfe00000);
722         flash_sector_erase_int(j); /*erase the first block of bank 2*/
723         j=flash_get_blk(0xbffe0000);
724         flash_sector_erase_int(j); /*erase the bootflag of bank 2*/
725     }
726 #endif
727 #if defined(CONFIG_BCM96358)
728     if (flash_get_total_size() == 0x800000) {
729         j=flash_get_blk(0xbe400000);
730         flash_sector_erase_int(j); /*erase the first block of bank 2*/
731         j=flash_get_blk(0xbe7e0000);
732         flash_sector_erase_int(j); /*erase the bootflag of bank 2*/
733     }
734 #endif  
735 }
736
737 /* bootflag will indicate which bank will be set */
738 int kerSysBootFlagSet(char bootflag)
739 {
740     int i = 0;
741     int sect_size = 0;
742     int sts = 0;
743     char *pTempBuf = NULL;
744     unsigned char bootnum;
745     int sector;
746     
747     unsigned int totalSize = (unsigned int) flash_get_total_size();
748
749 #if 1    
750 sector =bootflag?flash_get_blk(FLASH_BASE+totalSize-FLASH_RESERVED_AT_END-1):flash_get_blk(FLASH_BASE+(totalSize/2)-1);
751 bootnum=bootflag?*(unsigned char*) (FLASH_BASE+(totalSize/2)-1):*(unsigned char*) (FLASH_BASE+totalSize-FLASH_RESERVED_AT_END-1);  /*flash bank1 get bootnum from bank2*/  
752 #else
753 sector =bootflag?flash_get_blk(0xbffe0000):flash_get_blk(0xbfdf0000);
754 bootnum=bootflag?*(unsigned char*) (0xbfe00000-1):*(unsigned char*) (0xbfff0000-1);  /*flash bank1 get bootnum from bank2*/  
755 #endif
756
757 if ((bootnum >> 2)==0 && bootnum) {
758     bootnum=(bootnum+1);
759     if (bootnum>>2) bootnum>>=2;
760 }
761 else bootnum = 1;
762    
763         sect_size = flash_get_sector_size(sector);      /* denny 09/13/04' modified */
764         if ((pTempBuf = (char *) retriedKmalloc(sect_size)) == NULL) {
765             printk("failed to allocate memory with size: %d\n", sect_size);
766             return -1;
767         
768         }        
769         flash_read_buf(sector, 0, pTempBuf, sect_size); 
770         flash_sector_erase_int(sector);
771         *((char *) (pTempBuf+sect_size-1)) = bootnum;
772         if (flash_write_buf(sector, 0, pTempBuf, sect_size) != sect_size)
773         {
774             printk("Error writing flash sector %d.\n", i);
775             sts = -1;
776         }
777         retriedKfree(pTempBuf); 
778         printk("Next bbank %d/flag %d\n",bootflag,bootnum);
779         return sts;
780 }
781 #endif
782 // set nvram 
783 // return:
784 //  0 - ok
785 //  -1 - fail
786 int kerSysNvRamSet(char *string, int strLen, int offset)
787 {
788     int sts = 0;
789     char *pBuf = NULL;
790
791     if (strLen > NVRAM_LENGTH)
792         return -1;
793
794     if ((pBuf = getSharedBlks(fInfo.flash_nvram_start_blk,
795         (fInfo.flash_nvram_start_blk + fInfo.flash_nvram_number_blk))) == NULL)
796         return -1;
797
798     // set string to the memory buffer
799     memcpy((pBuf + fInfo.flash_nvram_blk_offset + offset), string, strLen);
800
801     if (setSharedBlks(fInfo.flash_nvram_start_blk, 
802         (fInfo.flash_nvram_number_blk + fInfo.flash_nvram_start_blk), pBuf) != 0)
803         sts = -1;
804     
805     retriedKfree(pBuf);
806
807     return sts;
808 }
809
810
811 /***********************************************************************
812  * Function Name: kerSysEraseNvRam
813  * Description  : Erase the NVRAM storage section of flash memory.
814  * Returns      : 1 -- ok, 0 -- fail
815  ***********************************************************************/
816 int kerSysEraseNvRam(void)
817 {
818     int sts = 1;
819     char *tempStorage = retriedKmalloc(NVRAM_LENGTH);
820     
821     // just write the whole buf with '0xff' to the flash
822     if (!tempStorage)
823         sts = 0;
824     else
825     {
826         memset(tempStorage, 0xff, NVRAM_LENGTH);
827         if (kerSysNvRamSet(tempStorage, NVRAM_LENGTH, 0) != 0)
828             sts = 0;
829         retriedKfree(tempStorage);
830     }
831
832     return sts;
833 }
834
835 /*==== add by Andrew (2004/09/14) ====*/
836 #if defined(CFG_XFER_TO_FACDEFLT)
837 int kerSysFactDefltGet(char *string, int strLen, int offset)
838 {
839     char *pBuf = NULL;
840
841     if (strLen > fInfo.flash_factdeflt_length)
842         return -1;
843
844     if ((pBuf = getSharedBlks(fInfo.flash_factdeflt_start_blk,
845         (fInfo.flash_factdeflt_start_blk + fInfo.flash_factdeflt_number_blk))) == NULL)
846         return -1;
847
848     // get string off the memory buffer
849     memcpy(string, (pBuf + fInfo.flash_factdeflt_blk_offset + offset), strLen);
850
851     retriedKfree(pBuf);
852
853     return 0;
854 }
855
856
857 // set factdeflt
858 // return:
859 //  0 - ok
860 //  -1 - fail
861 int kerSysFactDefltSet(char *string, int strLen, int offset)
862 {
863     int sts = 0;
864     char *pBuf = NULL;
865
866     if (strLen > fInfo.flash_factdeflt_length)
867         return -1;
868
869     if ((pBuf = getSharedBlks(fInfo.flash_factdeflt_start_blk,
870         (fInfo.flash_factdeflt_start_blk + fInfo.flash_factdeflt_number_blk))) == NULL)
871         return -1;
872
873     // set string to the memory buffer
874     memcpy((pBuf + fInfo.flash_factdeflt_blk_offset + offset), string, strLen);
875     if (setSharedBlks(fInfo.flash_factdeflt_start_blk, 
876         (fInfo.flash_factdeflt_number_blk + fInfo.flash_factdeflt_start_blk), pBuf) != 0)
877         sts = -1;
878     retriedKfree(pBuf);
879
880     return sts;
881 }
882 #endif
883 /*==== end ====*/
884 /*******************************************************************************
885  * PSI functions
886  *******************************************************************************/
887 // get psi data
888 // return:
889 //  0 - ok
890 //  -1 - fail
891 int kerSysPersistentGet(char *string, int strLen, int offset)
892 {
893     char *pBuf = NULL;
894
895     if (strLen > fInfo.flash_persistent_length)
896         return -1;
897
898     if ((pBuf = getSharedBlks(fInfo.flash_persistent_start_blk,
899         (fInfo.flash_persistent_start_blk + fInfo.flash_persistent_number_blk))) == NULL)
900         return -1;
901
902     // get string off the memory buffer
903     memcpy(string, (pBuf + fInfo.flash_persistent_blk_offset + offset), strLen);
904
905     retriedKfree(pBuf);
906
907     return 0;
908 }
909
910
911 // set psi 
912 // return:
913 //  0 - ok
914 //  -1 - fail
915 int kerSysPersistentSet(char *string, int strLen, int offset)
916 {
917     int sts = 0;
918     char *pBuf = NULL;
919
920     if (strLen > fInfo.flash_persistent_length)
921         return -1;
922
923     if ((pBuf = getSharedBlks(fInfo.flash_persistent_start_blk,
924         (fInfo.flash_persistent_start_blk + fInfo.flash_persistent_number_blk))) == NULL)
925         return -1;
926
927     // set string to the memory buffer
928     memcpy((pBuf + fInfo.flash_persistent_blk_offset + offset), string, strLen);
929
930     if (setSharedBlks(fInfo.flash_persistent_start_blk, 
931         (fInfo.flash_persistent_number_blk + fInfo.flash_persistent_start_blk), pBuf) != 0)
932         sts = -1;
933     
934     retriedKfree(pBuf);
935
936     return sts;
937 }
938
939 /*Michael: for fix crash when push reset button */
940 /* We add this because it happen only at 2Mflash 8M SDRAM. */
941 int kerSysPersistentSetRESET()
942 {
943     int sts = 0;
944     char *pBuf = NULL;
945
946 //    if (strLen > fInfo.flash_persistent_length)
947 //        return -1;
948     if ((pBuf = getSharedBlksRESET(fInfo.flash_persistent_start_blk,
949         (fInfo.flash_persistent_start_blk + fInfo.flash_persistent_number_blk))) == NULL)
950         return -1;
951     // set string to the memory buffer
952     memset((pBuf + fInfo.flash_persistent_blk_offset), 0xff, fInfo.flash_persistent_length);
953     // memcpy((pBuf + fInfo.flash_persistent_blk_offset + offset), string, strLen);
954     if (setSharedBlks(fInfo.flash_persistent_start_blk,
955         (fInfo.flash_persistent_number_blk + fInfo.flash_persistent_start_blk), pBuf) != 0)
956         sts = -1;
957     retriedKfree(pBuf);
958     return sts;
959 }
960
961 // flash bcm image 
962 // return: 
963 // 0 - ok
964 // !0 - the sector number fail to be flashed (should not be 0)
965 int kerSysBcmImageSet( int flash_start_addr, char *string, int size)
966 {
967     int sts;
968     int sect_size;
969     int blk_start;
970     int i;
971     char *pTempBuf = NULL;
972     int whole_image = 0;
973
974     blk_start = flash_get_blk(flash_start_addr);
975     if( blk_start < 0 )
976         return( -1 );
977
978     if (flash_start_addr == FLASH_BASE && size > FLASH_LENGTH_BOOT_ROM)
979         whole_image = 1;
980
981    /* write image to flash memory */
982     do 
983     {
984         sect_size = flash_get_sector_size(blk_start);
985 // NOTE: for memory problem in multiple PVC configuration, temporary get rid of kmalloc this 64K for now.
986 //        if ((pTempBuf = (char *)retriedKmalloc(sect_size)) == NULL)
987 //        {
988 //            printk("Failed to allocate memory with size: %d.  Reset the router...\n", sect_size);
989 //            kerSysMipsSoftReset();     // reset the board right away.
990 //        }
991         // for whole image, no check on psi
992         if (!whole_image && blk_start == fInfo.flash_persistent_start_blk)  // share the blk with psi
993         {
994             if (size > (sect_size - fInfo.flash_persistent_length))
995             {
996                 printk("Image is too big\n");
997                 break;          // image is too big. Can not overwrite to nvram
998             }
999             if ((pTempBuf = (char *)retriedKmalloc(sect_size)) == NULL)
1000             {
1001                printk("Failed to allocate memory with size: %d.  Reset the router...\n", sect_size);
1002                kerSysMipsSoftReset();     // reset the board right away.
1003             }
1004             flash_read_buf(blk_start, 0, pTempBuf, sect_size);
1005             if (copy_from_user((void *)pTempBuf,(void *)string, size) != 0)
1006                 break;  // failed ?
1007             flash_sector_erase_int(blk_start);     // erase blk before flash
1008             if (flash_write_buf(blk_start, 0, pTempBuf, sect_size) == sect_size) 
1009                 size = 0;   // break out and say all is ok
1010             retriedKfree(pTempBuf);
1011             break;
1012         }
1013         
1014         flash_sector_erase_int(blk_start);     // erase blk before flash
1015
1016         if (sect_size > size) 
1017         {
1018             if (size & 1) 
1019                 size++;
1020             sect_size = size;
1021         }
1022         
1023         if ((i = flash_write_buf(blk_start, 0, string, sect_size)) != sect_size) {
1024             break;
1025         }
1026         blk_start++;
1027         string += sect_size;
1028         size -= sect_size; 
1029     } while (size > 0);
1030
1031     if (whole_image)  
1032     {
1033         // If flashing a whole image, erase to end of flash.
1034         int total_blks = flash_get_numsectors();
1035         while( blk_start < total_blks )
1036         {
1037             flash_sector_erase_int(blk_start);
1038             blk_start++;
1039         }
1040     }
1041     if (pTempBuf)
1042         retriedKfree(pTempBuf);
1043
1044     if( size == 0 ) 
1045         sts = 0;  // ok
1046     else  
1047         sts = blk_start;    // failed to flash this sector
1048
1049     return sts;
1050 }
1051
1052 /***********************************************************************
1053  * Function Name: kerSysErasePersistent
1054  * Description  : Erase the Psi storage section of flash memory.
1055  * Returns      : 1 -- ok, 0 -- fail
1056  ***********************************************************************/
1057
1058 /* This funtion ONLY called by user when reset to default button is pressed */
1059
1060
1061 int kerSysErasePersistent(void)
1062 {
1063     int sts = 1;
1064     char *tempStorage = NULL;
1065     int i, size=0, unit = fInfo.flash_persistent_length/8;
1066     
1067 #if 0    
1068
1069     printk("psi 0x%08x #blks 0x%08x len 0x%08x offset 0x%08x \n",fInfo.flash_persistent_start_blk,fInfo.flash_persistent_number_blk,fInfo.flash_persistent_length,fInfo.flash_persistent_blk_offset);
1070     printk("pad 0x%08x #blks 0x%08x len 0x%08x offset 0x%08x \n",fInfo.flash_scratch_pad_start_blk,fInfo.flash_scratch_pad_number_blk,fInfo.flash_scratch_pad_length,fInfo.flash_scratch_pad_blk_offset);
1071     printk("nvram 0x%08x #blks 0x%08x len 0x%08x offset 0x%08x \n",fInfo.flash_nvram_start_blk,fInfo.flash_nvram_number_blk,fInfo.flash_nvram_length,fInfo.flash_nvram_blk_offset);
1072
1073     printk("\nErasing PSI storage section of flash memory....\n");
1074     for(i=0;i<7;i++) {
1075         tempStorage = retriedKmallocRESET(unit);
1076        // just write the whole buf with '0xff' to the flash
1077        if (!tempStorage) {
1078           sts = 0;
1079        } else {
1080           memset(tempStorage, 0xff, unit);
1081           if(kerSysPersistentSetRESET(tempStorage, unit, size) != 0)
1082               sts = 0;
1083           retriedKfree(tempStorage);
1084        }
1085        size += unit;
1086        if(!sts) {printk("Cannot alloc %d\n",i); return sts;}
1087        else printk("success in %d\n",i);
1088     }
1089
1090     unit = fInfo.flash_persistent_length - size;
1091     printk("try to alloc %d\n",unit);
1092     tempStorage = retriedKmalloc(unit);
1093     if (!tempStorage) {
1094        sts = 0;
1095     } else {
1096         printk("success in last\n");
1097        memset(tempStorage, 0xff, unit);
1098        if(kerSysPersistentSet(tempStorage, unit, size) != 0)
1099            sts = 0;
1100        retriedKfree(tempStorage);
1101     }
1102 #else
1103    printk("\nErasing PSI....\n");
1104    if (kerSysPersistentSetRESET() != 0)
1105               sts = 0;
1106 #endif
1107     printk("\nRebooting ADSL router.........");
1108     return sts;
1109 }
1110
1111
1112
1113 /*******************************************************************************
1114  * SP functions
1115  *******************************************************************************/
1116 // get sp data.  NOTE: memcpy work here -- not using copy_from/to_user
1117 // return:
1118 //  >0 - number of bytes copied to tokBuf
1119 //  -1 - fail
1120 int kerSysScratchPadGet(char *tokenId, char *tokBuf, int bufLen)
1121 {
1122     PSP_TOKEN pToken = NULL;
1123     char *pBuf = NULL;
1124     char *pShareBuf = NULL;
1125     char *startPtr = NULL;
1126     int usedLen;
1127     int sts = -1;
1128
1129     if (fInfo.flash_scratch_pad_length == 0)
1130         return sts;
1131
1132     if( bufLen >= (fInfo.flash_scratch_pad_length - sizeof(SP_HEADER) -
1133         sizeof(SP_TOKEN)) ) 
1134     {
1135         printk("Exceed scratch pad space by %d\n", bufLen -
1136             fInfo.flash_scratch_pad_length - sizeof(SP_HEADER) -
1137             sizeof(SP_TOKEN));
1138         return sts;
1139     }
1140
1141     if( (pShareBuf = getSharedBlks(fInfo.flash_scratch_pad_start_blk,
1142         (fInfo.flash_scratch_pad_start_blk +
1143         fInfo.flash_scratch_pad_number_blk))) == NULL )
1144     {
1145         return sts;
1146     }
1147
1148     // pBuf points to SP buf
1149     pBuf = pShareBuf + fInfo.flash_scratch_pad_blk_offset;  
1150
1151     if(memcmp(((PSP_HEADER)pBuf)->SPMagicNum, MAGIC_NUMBER, MAGIC_NUM_LEN) != 0) 
1152     {
1153         printk("Scratch pad is not initialized.\n");
1154         retriedKfree(pShareBuf);
1155         return sts;
1156     }
1157
1158     // search for the token
1159     usedLen = sizeof(SP_HEADER);
1160     startPtr = pBuf + sizeof(SP_HEADER);
1161     pToken = (PSP_TOKEN) startPtr;
1162     while( pToken->tokenName[0] != '\0' && pToken->tokenLen > 0 &&
1163         pToken->tokenLen < fInfo.flash_scratch_pad_length &&
1164         usedLen < fInfo.flash_scratch_pad_length )
1165     {
1166
1167         if (strncmp(pToken->tokenName, tokenId, TOKEN_NAME_LEN) == 0)
1168         {
1169             if ( pToken->tokenLen > bufLen )
1170             {
1171                 printk("The length %d of token %s is greater than buffer len %d.\n", pToken->tokenLen, pToken->tokenName, bufLen);
1172                 break;
1173             } else             
1174             sts = pToken->tokenLen;
1175             memcpy(tokBuf, startPtr + sizeof(SP_TOKEN), sts);
1176             break;
1177         }
1178
1179         usedLen += ((pToken->tokenLen + 0x03) & ~0x03);
1180         startPtr += sizeof(SP_TOKEN) + ((pToken->tokenLen + 0x03) & ~0x03);
1181         pToken = (PSP_TOKEN) startPtr;
1182     }
1183
1184     retriedKfree(pShareBuf);
1185
1186     return sts;
1187 }
1188
1189
1190 // set sp.  NOTE: memcpy work here -- not using copy_from/to_user
1191 // return:
1192 //  0 - ok
1193 //  -1 - fail
1194 int kerSysScratchPadSet(char *tokenId, char *tokBuf, int bufLen)
1195 {
1196     PSP_TOKEN pToken = NULL;
1197     char *pShareBuf = NULL;
1198     char *pBuf = NULL;
1199     SP_HEADER SPHead;
1200     SP_TOKEN SPToken;
1201     char *curPtr;
1202     int sts = -1;
1203
1204     if (fInfo.flash_scratch_pad_length == 0)
1205         return sts;
1206
1207     if( bufLen >= fInfo.flash_scratch_pad_length - sizeof(SP_HEADER) -
1208         sizeof(SP_TOKEN) )
1209     {
1210         printk("Scratch pad overflow by %d bytes.  Information not saved.\n",
1211             bufLen  - fInfo.flash_scratch_pad_length - sizeof(SP_HEADER) -
1212             sizeof(SP_TOKEN));
1213         return sts;
1214     }
1215
1216     if( (pShareBuf = getSharedBlks( fInfo.flash_scratch_pad_start_blk,
1217         (fInfo.flash_scratch_pad_start_blk +
1218         fInfo.flash_scratch_pad_number_blk) )) == NULL )
1219     {
1220         return sts;
1221     }
1222
1223     // pBuf points to SP buf
1224     pBuf = pShareBuf + fInfo.flash_scratch_pad_blk_offset;  
1225
1226     // form header info.
1227     memset((char *)&SPHead, 0, sizeof(SP_HEADER));
1228     memcpy(SPHead.SPMagicNum, MAGIC_NUMBER, MAGIC_NUM_LEN);
1229     SPHead.SPVersion = SP_VERSION;
1230
1231     // form token info.
1232     memset((char*)&SPToken, 0, sizeof(SP_TOKEN));
1233     strncpy(SPToken.tokenName, tokenId, TOKEN_NAME_LEN - 1);
1234     SPToken.tokenLen = bufLen;
1235
1236     if(memcmp(((PSP_HEADER)pBuf)->SPMagicNum, MAGIC_NUMBER, MAGIC_NUM_LEN) != 0)
1237     {
1238         // new sp, so just flash the token
1239         printk("No scratch pad found.  Initialize scratch pad...\n");
1240         memcpy(pBuf, (char *)&SPHead, sizeof(SP_HEADER));
1241         curPtr = pBuf + sizeof(SP_HEADER);
1242         memcpy(curPtr, (char *)&SPToken, sizeof(SP_TOKEN));
1243         curPtr += sizeof(SP_TOKEN);
1244         if( tokBuf )
1245             memcpy(curPtr, tokBuf, bufLen);
1246     }
1247     else  
1248     {
1249         int putAtEnd = 1;
1250         int curLen;
1251         int usedLen;
1252         int skipLen;
1253
1254         /* Calculate the used length. */
1255         usedLen = sizeof(SP_HEADER);
1256         curPtr = pBuf + sizeof(SP_HEADER);
1257         pToken = (PSP_TOKEN) curPtr;
1258         skipLen = (pToken->tokenLen + 0x03) & ~0x03;
1259         while( pToken->tokenName[0] >= 'A' && pToken->tokenName[0] <= 'z' &&
1260             strlen(pToken->tokenName) < TOKEN_NAME_LEN &&
1261             pToken->tokenLen > 0 &&
1262             pToken->tokenLen < fInfo.flash_scratch_pad_length &&
1263             usedLen < fInfo.flash_scratch_pad_length )
1264         {
1265             usedLen += sizeof(SP_TOKEN) + skipLen;
1266             curPtr += sizeof(SP_TOKEN) + skipLen;
1267             pToken = (PSP_TOKEN) curPtr;
1268             skipLen = (pToken->tokenLen + 0x03) & ~0x03;
1269         }
1270
1271         if( usedLen + SPToken.tokenLen + sizeof(SP_TOKEN) >
1272             fInfo.flash_scratch_pad_length )
1273         {
1274             printk("Scratch pad overflow by %d bytes.  Information not saved.\n",
1275                 (usedLen + SPToken.tokenLen + sizeof(SP_TOKEN)) -
1276                 fInfo.flash_scratch_pad_length);
1277             return sts;
1278         }
1279
1280         curPtr = pBuf + sizeof(SP_HEADER);
1281         curLen = sizeof(SP_HEADER);
1282         while( curLen < usedLen )
1283         {
1284             pToken = (PSP_TOKEN) curPtr;
1285             skipLen = (pToken->tokenLen + 0x03) & ~0x03;
1286             if (strncmp(pToken->tokenName, tokenId, TOKEN_NAME_LEN) == 0)
1287             {
1288                 // The token id already exists.
1289                 if( tokBuf && pToken->tokenLen == bufLen )
1290                 {
1291                     // The length of the new data and the existing data is the
1292                     // same.  Overwrite the existing data.
1293                     memcpy((curPtr+sizeof(SP_TOKEN)), tokBuf, bufLen);
1294                     putAtEnd = 0;
1295                 }
1296                 else
1297                 {
1298                     // The length of the new data and the existing data is
1299                     // different.  Shift the rest of the scratch pad to this
1300                     // token's location and put this token's data at the end.
1301                     char *nextPtr = curPtr + sizeof(SP_TOKEN) + skipLen;
1302                     int copyLen = usedLen - (curLen+sizeof(SP_TOKEN) + skipLen);
1303                     memcpy( curPtr, nextPtr, copyLen );
1304                     memset( curPtr + copyLen, 0x00, 
1305                         fInfo.flash_scratch_pad_length - (curLen + copyLen) );
1306                     usedLen -= sizeof(SP_TOKEN) + skipLen;
1307                 }
1308                 break;
1309             }
1310
1311             // get next token
1312             curPtr += sizeof(SP_TOKEN) + skipLen;
1313             curLen += sizeof(SP_TOKEN) + skipLen;
1314         } // end while
1315
1316         if( putAtEnd )
1317         {
1318             if( tokBuf )
1319             {
1320                 memcpy( pBuf + usedLen, &SPToken, sizeof(SP_TOKEN) );
1321                 memcpy( pBuf + usedLen + sizeof(SP_TOKEN), tokBuf, bufLen );
1322             }
1323             memcpy( pBuf, &SPHead, sizeof(SP_HEADER) );
1324         }
1325
1326     } // else if not new sp
1327
1328     sts = setSharedBlks(fInfo.flash_scratch_pad_start_blk, 
1329         (fInfo.flash_scratch_pad_number_blk + fInfo.flash_scratch_pad_start_blk),
1330         pShareBuf);
1331     
1332     retriedKfree(pShareBuf);
1333
1334     return sts;
1335
1336     
1337 }
1338
1339 // wipe out the scratchPad
1340 // return:
1341 //  0 - ok
1342 //  -1 - fail
1343 int kerSysScratchPadClearAll(void)
1344
1345     int sts = -1;
1346     char *pShareBuf = NULL;
1347     char *pBuf = NULL;
1348         
1349
1350     if (fInfo.flash_scratch_pad_length == 0)
1351         return sts;
1352     if( (pShareBuf = getSharedBlks( fInfo.flash_scratch_pad_start_blk,
1353         (fInfo.flash_scratch_pad_start_blk + fInfo.flash_scratch_pad_number_blk) )) == NULL )
1354         return sts;
1355     pBuf = pShareBuf + fInfo.flash_scratch_pad_blk_offset;  
1356     memset(pBuf, 0x00,  fInfo.flash_scratch_pad_length);
1357     sts = setSharedBlks(fInfo.flash_scratch_pad_start_blk,    
1358                 (fInfo.flash_scratch_pad_number_blk + fInfo.flash_scratch_pad_start_blk),  pBuf);
1359
1360    retriedKfree(pShareBuf);
1361         
1362    return sts;
1363 }
1364
1365 int kerSysFlashSizeGet(void)
1366 {
1367    return flash_get_total_size();
1368 }
1369
1370 int kerSysMemoryMappedFlashSizeGet(void)
1371 {
1372     return( flash_get_total_memory_mapped_size() );
1373 }
1374
1375 unsigned long kerSysReadFromFlash( void *toaddr, unsigned long fromaddr,
1376     unsigned long len )
1377 {
1378     int sect = flash_get_blk((int) fromaddr);
1379     unsigned char *start = flash_get_memptr(sect);
1380     flash_read_buf( sect, (int) fromaddr - (int) start, toaddr, len );
1381
1382     return( len );
1383 }
1384
1385 /*This function is copied from V2.10.1 to fix the bug SDRAM change from 16M to 8M 
1386   during upgrade include CFE */
1387 /***********************************************************************
1388  * Function Name: kerSysMemoryTypeSet
1389  * Description  : set the memory type 4 bytes
1390  * Returns      : 1 -- ok, 0 -- fail
1391  ***********************************************************************/
1392 int kerSysMemoryTypeSet(int flash_start_addr, char *string, int size)
1393 {
1394     int sect_size;
1395     int blk_start;
1396     char *pTempBuf;
1397
1398     blk_start = flash_get_blk(flash_start_addr);
1399     sect_size = flash_get_sector_size(blk_start);
1400     if ((pTempBuf = (char *) retriedKmalloc(sect_size)) == NULL)
1401     {
1402         printk("Failed to allocate memory with size: %d\n", sect_size);
1403         return 0;
1404     }
1405     flash_read_buf(blk_start, 0, pTempBuf, sect_size);
1406     memcpy(pTempBuf+SDRAM_TYPE_ADDRESS_OFFSET, string, size);
1407     flash_sector_erase_int(blk_start);     // erase blk before flash
1408 //    flash_ub(0);
1409     if (flash_write_buf(blk_start, 0, pTempBuf, sect_size) != sect_size)
1410         printk("Failed to flash the memory type\n");
1411 //    flash_reset_ub();
1412     return 1;
1413 }
1414
1415 /*This function is copied from V2.10.1 to fix the bug SDRAM change from 16M to 8M 
1416   during upgrade include CFE */
1417 /***********************************************************************
1418  * Function Name: kerSysMemoryTypeSet
1419  * Description  : set the memory type 4 bytes
1420  * Returns      : 1 -- ok, 0 -- fail
1421  ***********************************************************************/
1422 int kerSysThreadNumSet(int flash_start_addr, char *string, int size)
1423 {
1424     int sect_size;
1425     int blk_start;
1426     char *pTempBuf;
1427
1428     blk_start = flash_get_blk(flash_start_addr);
1429     sect_size = flash_get_sector_size(blk_start);
1430     if ((pTempBuf = (char *) retriedKmalloc(sect_size)) == NULL)
1431     {
1432         printk("Failed to allocate memory with size: %d\n", sect_size);
1433         return 0;
1434     }
1435     flash_read_buf(blk_start, 0, pTempBuf, sect_size);
1436     memcpy(pTempBuf+THREAD_NUM_ADDRESS_OFFSET, string, size);
1437     flash_sector_erase_int(blk_start);     // erase blk before flash
1438 //    flash_ub(0);
1439     if (flash_write_buf(blk_start, 0, pTempBuf, sect_size) != sect_size)
1440         printk("Failed to flash the thread num\n");
1441 //    flash_reset_ub();
1442     return 1;
1443 }
1444