Change nBytesPerChunk to nDataBytesPerChunk
[yaffs2.git] / patches / yaffs_mtdif2.c
1 /*
2  * YAFFS: Yet another FFS. A NAND-flash specific file system. 
3  * yaffs_mtdif.c  NAND mtd wrapper functions.
4  *
5  * Copyright (C) 2002 Aleph One Ltd.
6  *   for Toby Churchill Ltd and Brightstar Engineering
7  *
8  * Created by Charles Manning <charles@aleph1.co.uk>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2 as
12  * published by the Free Software Foundation.
13  *
14  */
15
16 /* mtd interface for YAFFS2 */
17
18 const char *yaffs_mtdif2_c_version =
19     "$Id: yaffs_mtdif2.c,v 1.1 2006-05-25 01:37:27 charles Exp $";
20
21 #include "yportenv.h"
22
23
24 #include "yaffs_mtdif2.h"
25
26 #include "linux/mtd/mtd.h"
27 #include "linux/types.h"
28 #include "linux/time.h"
29
30 #include "yaffs_packedtags2.h"
31
32
33 void nandmtd2_pt2buf(yaffs_Device *dev, yaffs_PackedTags2 *pt, int is_raw)
34 {
35         struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
36         __u8 *ptab = (__u8 *)pt; /* packed tags as bytes */
37         
38         int     i, j = 0, k, n;
39
40         /* Pack buffer with 0xff */
41         for (i = 0; i < mtd->oobsize; i++)
42                 dev->spareBuffer[i] = 0xff;
43                 
44         if(!is_raw){
45                 memcpy(dev->spareBuffer,pt,sizeof(yaffs_PackedTags2));
46         } else {
47                 j = 0;
48                 k = mtd->oobinfo.oobfree[j][0];
49                 n = mtd->oobinfo.oobfree[j][1];
50
51                 if (n == 0) {
52                         T(YAFFS_TRACE_ERROR, (TSTR("No OOB space for tags" TENDSTR)));
53                         YBUG();
54                 }
55
56                 for (i = 0; i < sizeof(yaffs_PackedTags2); i++) {
57                         if (n == 0) {
58                                 j++;
59                                 k = mtd->oobinfo.oobfree[j][0];
60                                 n = mtd->oobinfo.oobfree[j][1];
61                                 if (n == 0) {
62                                         T(YAFFS_TRACE_ERROR, (TSTR("No OOB space for tags" TENDSTR)));
63                                         YBUG();
64                                 }
65                         }
66                         dev->spareBuffer[k] = ptab[i];
67                         k++;
68                         n--;
69                 }
70         }
71
72 }
73
74 void nandmtd2_buf2pt(yaffs_Device *dev, yaffs_PackedTags2 *pt, int is_raw)
75 {
76         struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
77         int     i, j = 0, k, n;
78         __u8 *ptab = (__u8 *)pt; /* packed tags as bytes */
79
80
81         if (!is_raw) {
82         
83                 memcpy(pt,dev->spareBuffer,sizeof(yaffs_PackedTags2));
84         } else {
85                 j = 0;
86                 k = mtd->oobinfo.oobfree[j][0];
87                 n = mtd->oobinfo.oobfree[j][1];
88
89                 if (n == 0) {
90                         T(YAFFS_TRACE_ERROR, (TSTR("No space in OOB for tags" TENDSTR)));
91                         YBUG();
92                 }
93
94                 for (i = 0; i < sizeof(yaffs_PackedTags2); i++) {
95                         if (n == 0) {
96                                 j++;
97                                 k = mtd->oobinfo.oobfree[j][0];
98                                 n = mtd->oobinfo.oobfree[j][1];
99                                 if (n == 0) {
100                                         T(YAFFS_TRACE_ERROR, (TSTR("No space in OOB for tags" TENDSTR)));
101                                         YBUG();
102                                 }
103                         }
104                         ptab[i] = dev->spareBuffer[k];
105                         k++;
106                         n--;
107                 }
108         }
109                 
110 }
111
112 int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND,
113                                       const __u8 * data,
114                                       const yaffs_ExtendedTags * tags)
115 {
116         struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
117         size_t dummy;
118         int retval = 0;
119
120         loff_t addr = ((loff_t) chunkInNAND) * dev->nBytesPerChunk;
121
122         yaffs_PackedTags2 pt;
123
124         T(YAFFS_TRACE_MTD,
125           (TSTR
126            ("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p"
127             TENDSTR), chunkInNAND, data, tags));
128
129         if (tags) {
130                 yaffs_PackTags2(&pt, tags);
131         }
132
133         if (data && tags) {
134                         nandmtd2_pt2buf(dev, &pt, 0);
135                         retval =
136                             mtd->write_ecc(mtd, addr, dev->nBytesPerChunk,
137                                            &dummy, data, dev->spareBuffer,
138                                            NULL);
139
140         } else {
141         
142                 T(YAFFS_TRACE_ALWAYS,
143                   (TSTR
144                   ("Write chunk with null tags or data!" TENDSTR)));
145                 YBUG();
146         }
147
148         if (retval == 0)
149                 return YAFFS_OK;
150         else
151                 return YAFFS_FAIL;
152 }
153
154 int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,
155                                        __u8 * data, yaffs_ExtendedTags * tags)
156 {
157         struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
158         size_t dummy;
159         int retval = 0;
160
161         loff_t addr = ((loff_t) chunkInNAND) * dev->nBytesPerChunk;
162
163         yaffs_PackedTags2 pt;
164
165         T(YAFFS_TRACE_MTD,
166           (TSTR
167            ("nandmtd2_ReadChunkWithTagsToNAND chunk %d data %p tags %p"
168             TENDSTR), chunkInNAND, data, tags));
169
170         if (0 && data && tags) {
171                         retval =
172                             mtd->read_ecc(mtd, addr, dev->nBytesPerChunk,
173                                           &dummy, data, dev->spareBuffer,
174                                           NULL);
175                         nandmtd2_buf2pt(dev, &pt, 0);
176         } else {
177                 if (data)
178                         retval =
179                             mtd->read(mtd, addr, dev->nBytesPerChunk, &dummy,
180                                       data);
181                 if (tags) {
182                         retval =
183                             mtd->read_oob(mtd, addr, mtd->oobsize, &dummy,
184                                           dev->spareBuffer);
185                         nandmtd2_buf2pt(dev, &pt, 1);
186                 }
187         }
188
189         if (tags)
190                 yaffs_UnpackTags2(tags, &pt);
191
192         if (retval == 0)
193                 return YAFFS_OK;
194         else
195                 return YAFFS_FAIL;
196 }
197
198 int nandmtd2_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo)
199 {
200         struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
201         int retval;
202         T(YAFFS_TRACE_MTD,
203           (TSTR("nandmtd2_MarkNANDBlockBad %d" TENDSTR), blockNo));
204
205         retval =
206             mtd->block_markbad(mtd,
207                                blockNo * dev->nChunksPerBlock *
208                                dev->nBytesPerChunk);
209
210         if (retval == 0)
211                 return YAFFS_OK;
212         else
213                 return YAFFS_FAIL;
214
215 }
216
217 int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
218                             yaffs_BlockState * state, int *sequenceNumber)
219 {
220         struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
221         int retval;
222
223         T(YAFFS_TRACE_MTD,
224           (TSTR("nandmtd2_QueryNANDBlock %d" TENDSTR), blockNo));
225         retval =
226             mtd->block_isbad(mtd,
227                              blockNo * dev->nChunksPerBlock *
228                              dev->nBytesPerChunk);
229
230         if (retval) {
231                 T(YAFFS_TRACE_MTD, (TSTR("block is bad" TENDSTR)));
232
233                 *state = YAFFS_BLOCK_STATE_DEAD;
234                 *sequenceNumber = 0;
235         } else {
236                 yaffs_ExtendedTags t;
237                 nandmtd2_ReadChunkWithTagsFromNAND(dev,
238                                                    blockNo *
239                                                    dev->nChunksPerBlock, NULL,
240                                                    &t);
241
242                 if (t.chunkUsed) {
243                         *sequenceNumber = t.sequenceNumber;
244                         *state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
245                 } else {
246                         *sequenceNumber = 0;
247                         *state = YAFFS_BLOCK_STATE_EMPTY;
248                 }
249
250                 T(YAFFS_TRACE_MTD,
251                   (TSTR("block is OK seq %d state %d" TENDSTR), *sequenceNumber,
252                    *state));
253         }
254
255         if (retval == 0)
256                 return YAFFS_OK;
257         else
258                 return YAFFS_FAIL;
259 }
260