tizen 2.4 release
[kernel/u-boot-tm1.git] / fs / yaffs2 / yaffs_convert.c
1 #include <asm/arch/sci_types.h>
2 #include <nand.h>
3 #include <linux/mtd/mtd.h>
4 #include <linux/mtd/nand.h>
5 #include "yaffs_format_data_translate.h"
6 #define TRANS_CODE_SIZE         (12 * 1024)
7 #define DATA_BUFFER_SIZE        (TRANS_CODE_SIZE * 2)
8
9 #define NAND_SUCCESS                0
10 #define NAND_SYSTEM_ERROR           1
11 #define NAND_UNKNOWN_DEVICE         2
12 #define NAND_INVALID_DEVICE_SIZE    3
13 #define NAND_INCOMPATIBLE_PART      4
14 #define NAND_INVALID_ADDR           5
15 #define NAND_INVALID_SIZE           6
16 extern int nand_curr_device;
17 unsigned long  yaffs_buffer_size = 0;
18 unsigned long g_BigSize = 0;
19 unsigned long g_ReadBufLen = 0;
20 unsigned long code_yaffs_buflen = 0;
21 unsigned long code_yaffs_onewrite = 0;
22 unsigned char *g_BigBUF = NULL;
23
24 int nand_write_to_device(int dev_id,unsigned int size, unsigned char *buf)
25 {
26         struct mtd_info *nand;
27         struct nand_chip *chip;
28         int ret=0,pos;
29         int cur_offset = get_end_write_pos();
30
31         if ((dev_id < 0) || (dev_id >= CONFIG_SYS_MAX_NAND_DEVICE))
32                 return NAND_SYSTEM_ERROR;
33         nand = &nand_info[dev_id];
34         chip = nand->priv;
35         //find a good block to write 
36         while(!(cur_offset & (nand->erasesize-1))) {
37 //              printf("function: %s to check bad block, check address 0x%x\n", __FUNCTION__,cur_offset&(~(nand->erasesize - 1)));
38                 if (nand_block_isbad(nand, cur_offset&(~(nand->erasesize - 1)))) {
39                         printf("%s skip bad block 0x%x\n", __FUNCTION__, cur_offset&(~(nand->erasesize - 1)));
40                         cur_offset = (cur_offset + nand->erasesize)&(~(nand->erasesize - 1));
41                 } else {
42                         break;
43                 }
44         }
45
46         if(size != (nand->writesize + nand->oobsize)){
47                 return NAND_INVALID_SIZE;
48         }
49
50         chip->ops.mode = MTD_OOB_AUTO;
51         chip->ops.len = nand->writesize;
52         chip->ops.datbuf = (uint8_t *)buf;
53         chip->ops.oobbuf = (uint8_t *)buf + nand->writesize;
54         chip->ops.ooblen = sizeof(yaffs_PackedTags2);
55         chip->ops.ooboffs = 0;
56
57 //      printf("call nand_do_write_ops cur_offset = 0x%x\n",cur_offset );
58         ret = nand_do_write_ops(nand, (unsigned long long)cur_offset, &(chip->ops));
59         if (0 == ret) {
60                 cur_offset += nand->writesize;
61         } else {
62                 printf("\nwrite error, mark bad block : 0x%08x\n", cur_offset);
63                 nand->block_markbad(nand, cur_offset&~(nand->erasesize - 1));
64                 printf("find new good partition to move and write data again\n");
65                 move2goodblk(nand, 1);
66                 printf("move and write end. new write pos : 0x%08x\n", cur_offset);
67                 ret = 0;
68         }
69         set_current_write_pos(cur_offset);
70         return NAND_SUCCESS;
71 }
72
73 int init_yaffs_convert_variables(int writesize,int oobsize,int is_yaffs)
74 {
75         int ret;
76         yaffs_buffer_size = (DATA_BUFFER_SIZE + (DATA_BUFFER_SIZE / writesize) * oobsize);
77
78         if(g_BigBUF != NULL)
79                 return 1;
80         if (is_yaffs == 0) {
81                 code_yaffs_buflen = DATA_BUFFER_SIZE;
82                 code_yaffs_onewrite = writesize;
83         } else if (is_yaffs == 1) {
84                 code_yaffs_buflen = yaffs_buffer_size;
85                 code_yaffs_onewrite = writesize + oobsize;
86         }
87         
88         g_BigSize = 0;
89         if (g_BigBUF == NULL)
90                 g_BigBUF = (unsigned char *)malloc(yaffs_buffer_size);
91
92         if (g_BigBUF == NULL) {
93                 printf("malloc is wrong : %d\n", yaffs_buffer_size);
94                 ret = NAND_SYSTEM_ERROR;                
95                 return 0;
96         }
97         memset(g_BigBUF, 0xff, yaffs_buffer_size);
98         g_ReadBufLen = 0;
99         printf("code_yaffs_onewrite = %d  code_yaffs_buflen = %d  yaffs_buffer_size = %d\n", code_yaffs_onewrite, code_yaffs_buflen, yaffs_buffer_size);
100         return 1;
101
102 }
103 int yaffs2_convertAndWrite(int last_flag,int writesize,int oobsize,char *buffer)
104 {
105         yaffs_page src = {0};
106         yaffs_page dst = {0};
107         int count = 0;
108         unsigned int size_threshold = 0;
109         int ret = NAND_SUCCESS;
110         unsigned int remaindata = 0;
111
112         src.oobsize = 64;
113         src.pagesize = 2048;
114         src.p_pagedata = g_BigBUF;
115         dst.oobsize = oobsize;
116         dst.pagesize = writesize;
117         dst.p_pagedata = buffer;
118         count = dst.pagesize/src.pagesize;
119         size_threshold = (src.oobsize + src.pagesize)*count;
120         if(last_flag){
121                 size_threshold = src.oobsize + src.pagesize;
122         }
123         while ((g_BigSize - g_ReadBufLen) >= size_threshold) {
124                 //we have received more than one page data.
125                 count = yaffs_page_translate(&src, &dst);
126         //      printf("trans_count= 0x%x ,Big=0x%x ,read=0x%x, threshod=0x%x\n",count,g_BigSize,g_ReadBufLen,size_threshold);
127                 if(count > 0){
128                         //update global buffer
129                         g_ReadBufLen += count*(src.oobsize + src.pagesize);
130                         //update src data stream pointer
131                         src.p_pagedata = (unsigned char*)&src.p_pagedata[count*(src.oobsize + src.pagesize)];
132                         //restore one page data
133                         ret = nand_write_to_device(nand_curr_device,dst.pagesize+ dst.oobsize, dst.p_pagedata);
134                         if(ret != NAND_SUCCESS){
135                                 return NAND_SYSTEM_ERROR;
136                         }
137                 }
138         }
139
140         remaindata = g_BigSize - g_ReadBufLen;
141         memcpy(g_BigBUF, g_BigBUF + g_ReadBufLen, remaindata);
142         memset(g_BigBUF + remaindata, 0xff, yaffs_buffer_size - remaindata);
143         g_BigSize = remaindata;
144         g_ReadBufLen = 0;
145
146         return ret;
147 }
148
149 void save_to_convert_buffer(char *buffer, int size)
150 {
151         memcpy((g_BigBUF + g_BigSize), buffer, size);
152         g_BigSize += size;
153         //printf("g_BigSize = %d code_yaffs_buflen=%d\n",g_BigSize,code_yaffs_buflen);
154 }
155 int convert_buffer_is_full(void)
156 {
157         if (g_BigSize < (code_yaffs_buflen / 2))
158                 return 0;
159         return 1;
160 }
161 void set_convert_buffer(char *buffer,int size)
162 {
163         g_BigBUF = buffer;
164         g_BigSize = size;
165 }