comparison packages/fs/yaffs/current/src/patches/yaffs_mtdif2.c @ 425:dea4d7d250ad ecos

Move sources into packages/fs/yaffs/current/src/
author Ross Younger <wry@ecoscentric.com>
date Fri, 14 May 2010 16:03:09 +0100
parents patches/yaffs_mtdif2.c@c6c9df8d8c26
children
comparison
equal deleted inserted replaced
424:d21d6fd33e63 425:dea4d7d250ad
1 /*
2 * YAFFS: Yet another FFS. A NAND-flash specific file system.
3 *
4 * Copyright (C) 2002 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 /* mtd interface for YAFFS2 */
15
16 const char *yaffs_mtdif2_c_version =
17 "$Id: yaffs_mtdif2.c,v 1.2 2007-03-07 08:05:58 colin Exp $";
18
19 #include "yportenv.h"
20
21
22 #include "yaffs_mtdif2.h"
23
24 #include "linux/mtd/mtd.h"
25 #include "linux/types.h"
26 #include "linux/time.h"
27
28 #include "yaffs_packedtags2.h"
29
30
31 void nandmtd2_pt2buf(yaffs_Device *dev, yaffs_PackedTags2 *pt, int is_raw)
32 {
33 struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
34 __u8 *ptab = (__u8 *)pt; /* packed tags as bytes */
35
36 int i, j = 0, k, n;
37
38 /* Pack buffer with 0xff */
39 for (i = 0; i < mtd->oobsize; i++)
40 dev->spareBuffer[i] = 0xff;
41
42 if(!is_raw){
43 memcpy(dev->spareBuffer,pt,sizeof(yaffs_PackedTags2));
44 } else {
45 j = 0;
46 k = mtd->oobinfo.oobfree[j][0];
47 n = mtd->oobinfo.oobfree[j][1];
48
49 if (n == 0) {
50 T(YAFFS_TRACE_ERROR, (TSTR("No OOB space for tags" TENDSTR)));
51 YBUG();
52 }
53
54 for (i = 0; i < sizeof(yaffs_PackedTags2); i++) {
55 if (n == 0) {
56 j++;
57 k = mtd->oobinfo.oobfree[j][0];
58 n = mtd->oobinfo.oobfree[j][1];
59 if (n == 0) {
60 T(YAFFS_TRACE_ERROR, (TSTR("No OOB space for tags" TENDSTR)));
61 YBUG();
62 }
63 }
64 dev->spareBuffer[k] = ptab[i];
65 k++;
66 n--;
67 }
68 }
69
70 }
71
72 void nandmtd2_buf2pt(yaffs_Device *dev, yaffs_PackedTags2 *pt, int is_raw)
73 {
74 struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
75 int i, j = 0, k, n;
76 __u8 *ptab = (__u8 *)pt; /* packed tags as bytes */
77
78
79 if (!is_raw) {
80
81 memcpy(pt,dev->spareBuffer,sizeof(yaffs_PackedTags2));
82 } else {
83 j = 0;
84 k = mtd->oobinfo.oobfree[j][0];
85 n = mtd->oobinfo.oobfree[j][1];
86
87 if (n == 0) {
88 T(YAFFS_TRACE_ERROR, (TSTR("No space in OOB for tags" TENDSTR)));
89 YBUG();
90 }
91
92 for (i = 0; i < sizeof(yaffs_PackedTags2); i++) {
93 if (n == 0) {
94 j++;
95 k = mtd->oobinfo.oobfree[j][0];
96 n = mtd->oobinfo.oobfree[j][1];
97 if (n == 0) {
98 T(YAFFS_TRACE_ERROR, (TSTR("No space in OOB for tags" TENDSTR)));
99 YBUG();
100 }
101 }
102 ptab[i] = dev->spareBuffer[k];
103 k++;
104 n--;
105 }
106 }
107
108 }
109
110 int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND,
111 const __u8 * data,
112 const yaffs_ExtendedTags * tags)
113 {
114 struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
115 size_t dummy;
116 int retval = 0;
117
118 loff_t addr = ((loff_t) chunkInNAND) * dev->nBytesPerChunk;
119
120 yaffs_PackedTags2 pt;
121
122 T(YAFFS_TRACE_MTD,
123 (TSTR
124 ("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p"
125 TENDSTR), chunkInNAND, data, tags));
126
127 if (tags) {
128 yaffs_PackTags2(&pt, tags);
129 }
130
131 if (data && tags) {
132 nandmtd2_pt2buf(dev, &pt, 0);
133 retval =
134 mtd->write_ecc(mtd, addr, dev->nBytesPerChunk,
135 &dummy, data, dev->spareBuffer,
136 NULL);
137
138 } else {
139
140 T(YAFFS_TRACE_ALWAYS,
141 (TSTR
142 ("Write chunk with null tags or data!" TENDSTR)));
143 YBUG();
144 }
145
146 if (retval == 0)
147 return YAFFS_OK;
148 else
149 return YAFFS_FAIL;
150 }
151
152 int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,
153 __u8 * data, yaffs_ExtendedTags * tags)
154 {
155 struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
156 size_t dummy;
157 int retval = 0;
158
159 loff_t addr = ((loff_t) chunkInNAND) * dev->nBytesPerChunk;
160
161 yaffs_PackedTags2 pt;
162
163 T(YAFFS_TRACE_MTD,
164 (TSTR
165 ("nandmtd2_ReadChunkWithTagsToNAND chunk %d data %p tags %p"
166 TENDSTR), chunkInNAND, data, tags));
167
168 if (0 && data && tags) {
169 retval =
170 mtd->read_ecc(mtd, addr, dev->nBytesPerChunk,
171 &dummy, data, dev->spareBuffer,
172 NULL);
173 nandmtd2_buf2pt(dev, &pt, 0);
174 } else {
175 if (data)
176 retval =
177 mtd->read(mtd, addr, dev->nBytesPerChunk, &dummy,
178 data);
179 if (tags) {
180 retval =
181 mtd->read_oob(mtd, addr, mtd->oobsize, &dummy,
182 dev->spareBuffer);
183 nandmtd2_buf2pt(dev, &pt, 1);
184 }
185 }
186
187 if (tags)
188 yaffs_UnpackTags2(tags, &pt);
189
190 if (retval == 0)
191 return YAFFS_OK;
192 else
193 return YAFFS_FAIL;
194 }
195
196 int nandmtd2_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo)
197 {
198 struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
199 int retval;
200 T(YAFFS_TRACE_MTD,
201 (TSTR("nandmtd2_MarkNANDBlockBad %d" TENDSTR), blockNo));
202
203 retval =
204 mtd->block_markbad(mtd,
205 blockNo * dev->nChunksPerBlock *
206 dev->nBytesPerChunk);
207
208 if (retval == 0)
209 return YAFFS_OK;
210 else
211 return YAFFS_FAIL;
212
213 }
214
215 int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
216 yaffs_BlockState * state, int *sequenceNumber)
217 {
218 struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
219 int retval;
220
221 T(YAFFS_TRACE_MTD,
222 (TSTR("nandmtd2_QueryNANDBlock %d" TENDSTR), blockNo));
223 retval =
224 mtd->block_isbad(mtd,
225 blockNo * dev->nChunksPerBlock *
226 dev->nBytesPerChunk);
227
228 if (retval) {
229 T(YAFFS_TRACE_MTD, (TSTR("block is bad" TENDSTR)));
230
231 *state = YAFFS_BLOCK_STATE_DEAD;
232 *sequenceNumber = 0;
233 } else {
234 yaffs_ExtendedTags t;
235 nandmtd2_ReadChunkWithTagsFromNAND(dev,
236 blockNo *
237 dev->nChunksPerBlock, NULL,
238 &t);
239
240 if (t.chunkUsed) {
241 *sequenceNumber = t.sequenceNumber;
242 *state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
243 } else {
244 *sequenceNumber = 0;
245 *state = YAFFS_BLOCK_STATE_EMPTY;
246 }
247
248 T(YAFFS_TRACE_MTD,
249 (TSTR("block is OK seq %d state %d" TENDSTR), *sequenceNumber,
250 *state));
251 }
252
253 if (retval == 0)
254 return YAFFS_OK;
255 else
256 return YAFFS_FAIL;
257 }
258