d721fa636bf7234c6c3319abdddc5588cb327c5a
[yaffs2.git] / yaffs_nand.c
1 /*
2  * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
3  *
4  * Copyright (C) 2002-2010 Aleph One Ltd.
5  *   for Toby Churchill Ltd and Brightstar Engineering
6  *
7  * Created by Charles Manning <charles@aleph1.co.uk>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License version 2 as
11  * published by the Free Software Foundation.
12  */
13
14 #include "yaffs_nand.h"
15 #include "yaffs_tagscompat.h"
16 #include "yaffs_tagsvalidity.h"
17
18 #include "yaffs_getblockinfo.h"
19
20 int yaffs_rd_chunk_tags_nand(yaffs_dev_t *dev, int nand_chunk,
21                                            __u8 *buffer,
22                                            yaffs_ext_tags *tags)
23 {
24         int result;
25         yaffs_ext_tags local_tags;
26
27         int realigned_chunk = nand_chunk - dev->chunk_offset;
28
29         dev->n_page_reads++;
30
31         /* If there are no tags provided, use local tags to get prioritised gc working */
32         if (!tags)
33                 tags = &local_tags;
34
35         if (dev->param.read_chunk_tags_fn)
36                 result = dev->param.read_chunk_tags_fn(dev, realigned_chunk, buffer,
37                                                       tags);
38         else
39                 result = yaffs_tags_compat_rd(dev,
40                                                                         realigned_chunk,
41                                                                         buffer,
42                                                                         tags);
43         if (tags &&
44            tags->ecc_result > YAFFS_ECC_RESULT_NO_ERROR) {
45
46                 yaffs_block_info_t *bi;
47                 bi = yaffs_get_block_info(dev, nand_chunk/dev->param.chunks_per_block);
48                 yaffs_handle_chunk_error(dev, bi);
49         }
50
51         return result;
52 }
53
54 int yaffs_wr_chunk_tags_nand(yaffs_dev_t *dev,
55                                                    int nand_chunk,
56                                                    const __u8 *buffer,
57                                                    yaffs_ext_tags *tags)
58 {
59
60         dev->n_page_writes++;
61
62         nand_chunk -= dev->chunk_offset;
63
64
65         if (tags) {
66                 tags->seq_number = dev->seq_number;
67                 tags->chunk_used = 1;
68                 if (!yaffs_validate_tags(tags)) {
69                         T(YAFFS_TRACE_ERROR,
70                           (TSTR("Writing uninitialised tags" TENDSTR)));
71                         YBUG();
72                 }
73                 T(YAFFS_TRACE_WRITE,
74                   (TSTR("Writing chunk %d tags %d %d" TENDSTR), nand_chunk,
75                    tags->obj_id, tags->chunk_id));
76         } else {
77                 T(YAFFS_TRACE_ERROR, (TSTR("Writing with no tags" TENDSTR)));
78                 YBUG();
79         }
80
81         if (dev->param.write_chunk_tags_fn)
82                 return dev->param.write_chunk_tags_fn(dev, nand_chunk, buffer,
83                                                      tags);
84         else
85                 return yaffs_tags_compat_wr(dev,
86                                                                        nand_chunk,
87                                                                        buffer,
88                                                                        tags);
89 }
90
91 int yaffs_mark_bad(yaffs_dev_t *dev, int block_no)
92 {
93         block_no -= dev->block_offset;
94
95
96         if (dev->param.bad_block_fn)
97                 return dev->param.bad_block_fn(dev, block_no);
98         else
99                 return yaffs_tags_compat_mark_bad(dev, block_no);
100 }
101
102 int yaffs_query_init_block_state(yaffs_dev_t *dev,
103                                                  int block_no,
104                                                  yaffs_block_state_t *state,
105                                                  __u32 *seq_number)
106 {
107         block_no -= dev->block_offset;
108
109         if (dev->param.query_block_fn)
110                 return dev->param.query_block_fn(dev, block_no, state, seq_number);
111         else
112                 return yaffs_tags_compat_query_block(dev, block_no,
113                                                              state,
114                                                              seq_number);
115 }
116
117
118 int yaffs_erase_block(struct yaffs_dev_s *dev,
119                                   int flash_block)
120 {
121         int result;
122
123         flash_block -= dev->block_offset;
124
125         dev->n_erasures++;
126
127         result = dev->param.erase_fn(dev, flash_block);
128
129         return result;
130 }
131
132 int yaffs_init_nand(struct yaffs_dev_s *dev)
133 {
134         if(dev->param.initialise_flash_fn)
135                 return dev->param.initialise_flash_fn(dev);
136         return YAFFS_OK;
137 }
138
139
140