1 From ian@brightstareng
.com Fri May
18 15:06:49 2007
2 From ian@brightstareng
.com Fri May
18 15:08:21 2007
3 Received
: from
206.173.66.57.ptr
.us
.xo
.net ([206.173.66.57] helo
=zebra
.brightstareng
.com
)
4 by apollo
.linkchoose
.co
.uk with
esmtp (Exim
4.60)
5 (envelope
-from
<ian@brightstareng
.com
>)
7 for david
.goodenough@linkchoose
.co
.uk
; Fri
, 18 May
2007 15:08:21 +0100
8 Received
: from
localhost (localhost
.localdomain
[127.0.0.1])
9 by zebra
.brightstareng
.com (Postfix
) with ESMTP
10 id
4819F28C004
; Fri
, 18 May
2007 10:07:49 -0400 (EDT
)
11 Received
: from zebra
.brightstareng
.com ([127.0.0.1])
12 by
localhost (zebra
[127.0.0.1]) (amavisd
-new, port
10024) with ESMTP
13 id
05328-06; Fri
, 18 May
2007 10:07:16 -0400 (EDT
)
14 Received
: from
pippin (unknown
[192.168.1.25])
15 by zebra
.brightstareng
.com (Postfix
) with ESMTP
16 id
8BEF528C1BC
; Fri
, 18 May
2007 10:06:53 -0400 (EDT
)
17 From
: Ian McDonnell
<ian@brightstareng
.com
>
18 To
: David Goodenough
<david
.goodenough@linkchoose
.co
.uk
>
19 Subject
: Re
: something tested
this time
-- yaffs_mtdif1
-compat
.c
20 Date
: Fri
, 18 May
2007 10:06:49 -0400
21 User
-Agent
: KMail
/1.9.1
22 References
: <200705142207.06909.ian@brightstareng
.com
> <200705171131.53536.ian@brightstareng
.com
> <200705181334.32166.david
.goodenough@linkchoose
.co
.uk
>
23 In
-Reply
-To
: <200705181334.32166.david
.goodenough@linkchoose
.co
.uk
>
24 Cc
: Andrea Conti
<alyf@alyf
.net
>,
25 Charles Manning
<manningc2@actrix
.gen
.nz
>
27 Content
-Type
: Multipart
/Mixed
;
28 boundary
="Boundary-00=_5LbTGmt62YoutxM"
29 Message
-Id
: <200705181006.49860.ian@brightstareng
.com
>
30 X
-Virus
-Scanned
: by amavisd
-new at brightstareng
.com
33 X
-KMail
-EncryptionState
:
34 X
-KMail
-SignatureState
:
37 --Boundary
-00=_5LbTGmt62YoutxM
38 Content
-Type
: text
/plain
;
40 Content
-Transfer
-Encoding
: 7bit
41 Content
-Disposition
: inline
45 On Friday
18 May
2007 08:34, you wrote
:
46 > Yea team
. With
this fix in
place (I put it in the wrong place
47 > at first
) I can now mount
and ls the Yaffs partition without
52 Attached is a newer yaffs_mtdif1
.c with a bandaid to help the
53 2.6.18 and 2.6.19 versions of MTD
not trip on the oob read
.
54 See the LINUX_VERSION_CODE conditional in
55 nandmtd1_ReadChunkWithTagsFromNAND
.
59 --Boundary
-00=_5LbTGmt62YoutxM
60 Content
-Type
: text
/x
-csrc
;
61 charset
="iso-8859-15";
63 Content
-Transfer
-Encoding
: 7bit
64 Content
-Disposition
: attachment
;
65 filename
="yaffs_mtdif1.c"
68 * YAFFS: Yet another FFS. A NAND-flash specific file system.
69 * yaffs_mtdif1.c NAND mtd interface functions for small-page NAND.
71 * Copyright (C) 2002 Aleph One Ltd.
72 * for Toby Churchill Ltd and Brightstar Engineering
74 * This program is free software; you can redistribute it and/or modify
75 * it under the terms of the GNU General Public License version 2 as
76 * published by the Free Software Foundation.
80 * This module provides the interface between yaffs_nand.c and the
81 * MTD API. This version is used when the MTD interface supports the
82 * 'mtd_oob_ops' style calls to read_oob and write_oob, circa 2.6.17,
83 * and we have small-page NAND device.
85 * These functions are invoked via function pointers in yaffs_nand.c.
86 * This replaces functionality provided by functions in yaffs_mtdif.c
87 * and the yaffs_TagsCompatability functions in yaffs_tagscompat.c that are
88 * called in yaffs_mtdif.c when the function pointers are NULL.
89 * We assume the MTD layer is performing ECC (useNANDECC is true).
93 #include "yaffs_guts.h"
94 #include "yaffs_packedtags1.h"
95 #include "yaffs_tagscompat.h" // for yaffs_CalcTagsECC
97 #include "linux/kernel.h"
98 #include "linux/version.h"
99 #include "linux/types.h"
100 #include "linux/mtd/mtd.h"
102 /* Don't compile this module if we don't have MTD's mtd_oob_ops interface */
103 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
106 #ifndef CONFIG_YAFFS_9BYTE_TAGS
107 # define YTAG1_SIZE 8
109 # define YTAG1_SIZE 9
113 /* Use the following nand_ecclayout with MTD when using
114 * CONFIG_YAFFS_9BYTE_TAGS and the older on-NAND tags layout.
115 * If you have existing Yaffs images and the byte order differs from this,
116 * adjust 'oobfree' to match your existing Yaffs data.
118 * This nand_ecclayout scatters/gathers to/from the old-yaffs layout with the
119 * pageStatus byte (at NAND spare offset 4) scattered/gathered from/to
122 * Old-style on-NAND format: T0,T1,T2,T3,P,B,T4,T5,E0,E1,E2,T6,T7,E3,E4,E5
123 * We have/need PackedTags1 plus pageStatus: T0,T1,T2,T3,T4,T5,T6,T7,P
124 * where Tn are the tag bytes, En are MTD's ECC bytes, P is the pageStatus
125 * byte and B is the small-page bad-block indicator byte.
127 static struct nand_ecclayout nand_oob_16
= {
129 .eccpos
= { 8, 9, 10, 13, 14, 15 },
131 .oobfree
= { { 0, 4 }, { 6, 2 }, { 11, 2 }, { 4, 1 } }
135 /* Write a chunk (page) of data to NAND.
137 * Caller always provides ExtendedTags data which are converted to a more
138 * compact (packed) form for storage in NAND. A mini-ECC runs over the
139 * contents of the tags meta-data; used to valid the tags when read.
141 * - Pack ExtendedTags to PackedTags1 form
142 * - Compute mini-ECC for PackedTags1
143 * - Write data and packed tags to NAND.
145 * Note: Due to the use of the PackedTags1 meta-data which does not include
146 * a full sequence number (as found in the larger PackedTags2 form) it is
147 * necessary for Yaffs to re-write a chunk/page (just once) to mark it as
148 * discarded and dirty. This is not ideal: newer NAND parts are supposed
149 * to be written just once. When Yaffs performs this operation, this
150 * function is called with a NULL data pointer -- calling MTD write_oob
151 * without data is valid usage (2.6.17).
153 * Any underlying MTD error results in YAFFS_FAIL.
154 * Returns YAFFS_OK or YAFFS_FAIL.
156 int nandmtd1_WriteChunkWithTagsToNAND(yaffs_Device
*dev
,
157 int chunkInNAND
, const __u8
* data
, const yaffs_ExtendedTags
* etags
)
159 struct mtd_info
* mtd
= dev
->genericDevice
;
160 int chunkBytes
= dev
->nDataBytesPerChunk
;
161 loff_t addr
= ((loff_t
)chunkInNAND
) * chunkBytes
;
162 struct mtd_oob_ops ops
;
163 yaffs_PackedTags1 pt1
;
166 /* we assume that PackedTags1 and yaffs_Tags are compatible */
167 compile_time_assertion(sizeof(yaffs_PackedTags1
) == 12);
168 compile_time_assertion(sizeof(yaffs_Tags
) == 8);
170 yaffs_PackTags1(&pt1
, etags
);
171 yaffs_CalcTagsECC((yaffs_Tags
*)&pt1
);
173 /* When deleting a chunk, the upper layer provides only skeletal
174 * etags, one with chunkDeleted set. However, we need to update the
175 * tags, not erase them completely. So we use the NAND write property
176 * that only zeroed-bits stick and set tag bytes to all-ones and
177 * zero just the (not) deleted bit.
179 #ifndef CONFIG_YAFFS_9BYTE_TAGS
180 if (etags
->chunkDeleted
) {
181 memset(&pt1
, 0xff, 8);
182 /* clear delete status bit to indicate deleted */
186 ((__u8
*)&pt1
)[8] = 0xff;
187 if (etags
->chunkDeleted
) {
188 memset(&pt1
, 0xff, 8);
189 /* zero pageStatus byte to indicate deleted */
190 ((__u8
*)&pt1
)[8] = 0;
194 memset(&ops
, 0, sizeof(ops
));
195 ops
.mode
= MTD_OOB_AUTO
;
196 ops
.len
= (data
) ? chunkBytes
: 0;
197 ops
.ooblen
= YTAG1_SIZE
;
198 ops
.datbuf
= (__u8
*)data
;
199 ops
.oobbuf
= (__u8
*)&pt1
;
201 retval
= mtd
->write_oob(mtd
, addr
, &ops
);
203 yaffs_trace(YAFFS_TRACE_MTD
,
204 "write_oob failed, chunk %d, mtd error %d\n",
205 chunkInNAND
, retval
);
207 return retval
? YAFFS_FAIL
: YAFFS_OK
;
210 /* Return with empty ExtendedTags but add eccResult.
212 static int rettags(yaffs_ExtendedTags
* etags
, int eccResult
, int retval
)
215 memset(etags
, 0, sizeof(*etags
));
216 etags
->eccResult
= eccResult
;
221 /* Read a chunk (page) from NAND.
223 * Caller expects ExtendedTags data to be usable even on error; that is,
224 * all members except eccResult and blockBad are zeroed.
226 * - Check ECC results for data (if applicable)
227 * - Check for blank/erased block (return empty ExtendedTags if blank)
228 * - Check the PackedTags1 mini-ECC (correct if necessary/possible)
229 * - Convert PackedTags1 to ExtendedTags
230 * - Update eccResult and blockBad members to refect state.
232 * Returns YAFFS_OK or YAFFS_FAIL.
234 int nandmtd1_ReadChunkWithTagsFromNAND(yaffs_Device
*dev
,
235 int chunkInNAND
, __u8
* data
, yaffs_ExtendedTags
* etags
)
237 struct mtd_info
* mtd
= dev
->genericDevice
;
238 int chunkBytes
= dev
->nDataBytesPerChunk
;
239 loff_t addr
= ((loff_t
)chunkInNAND
) * chunkBytes
;
240 int eccres
= YAFFS_ECC_RESULT_NO_ERROR
;
241 struct mtd_oob_ops ops
;
242 yaffs_PackedTags1 pt1
;
246 memset(&ops
, 0, sizeof(ops
));
247 ops
.mode
= MTD_OOB_AUTO
;
248 ops
.len
= (data
) ? chunkBytes
: 0;
249 ops
.ooblen
= YTAG1_SIZE
;
251 ops
.oobbuf
= (__u8
*)&pt1
;
253 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
254 /* In MTD 2.6.18 to 2.6.19 nand_base.c:nand_do_read_oob() has a bug;
255 * help it out with ops.len = ops.ooblen when ops.datbuf == NULL.
257 ops
.len
= (ops
.datbuf
) ? ops
.len
: ops
.ooblen
;
259 /* Read page and oob using MTD.
260 * Check status and determine ECC result.
262 retval
= mtd
->read_oob(mtd
, addr
, &ops
);
264 yaffs_trace(YAFFS_TRACE_MTD
,
265 "read_oob failed, chunk %d, mtd error %d\n",
266 chunkInNAND
, retval
);
275 /* MTD's ECC fixed the data */
276 eccres
= YAFFS_ECC_RESULT_FIXED
;
281 /* MTD's ECC could not fix the data */
285 rettags(etags
, YAFFS_ECC_RESULT_UNFIXED
, 0);
286 etags
->blockBad
= (mtd
->block_isbad
)(mtd
, addr
);
290 /* Check for a blank/erased chunk.
292 if (yaffs_CheckFF((__u8
*)&pt1
, 8)) {
293 /* when blank, upper layers want eccResult to be <= NO_ERROR */
294 return rettags(etags
, YAFFS_ECC_RESULT_NO_ERROR
, YAFFS_OK
);
297 #ifndef CONFIG_YAFFS_9BYTE_TAGS
298 /* Read deleted status (bit) then return it to it's non-deleted
299 * state before performing tags mini-ECC check. pt1.deleted is
302 deleted
= !pt1
.deleted
;
305 (void) deleted
; /* not used */
308 /* Check the packed tags mini-ECC and correct if necessary/possible.
310 retval
= yaffs_CheckECCOnTags((yaffs_Tags
*)&pt1
);
313 /* no tags error, use MTD result */
316 /* recovered tags-ECC error */
318 eccres
= YAFFS_ECC_RESULT_FIXED
;
321 /* unrecovered tags-ECC error */
322 dev
->tagsEccUnfixed
++;
323 return rettags(etags
, YAFFS_ECC_RESULT_UNFIXED
, YAFFS_FAIL
);
326 /* Unpack the tags to extended form and set ECC result.
327 * [set shouldBeFF just to keep yaffs_UnpackTags1 happy]
329 pt1
.shouldBeFF
= 0xFFFFFFFF;
330 yaffs_UnpackTags1(etags
, &pt1
);
331 etags
->eccResult
= eccres
;
333 /* Set deleted state.
335 #ifndef CONFIG_YAFFS_9BYTE_TAGS
336 etags
->chunkDeleted
= deleted
;
338 etags
->chunkDeleted
= (yaffs_CountBits(((__u8
*)&pt1
)[8]) < 7);
345 * This is a persistant state.
346 * Use of this function should be rare.
348 * Returns YAFFS_OK or YAFFS_FAIL.
350 int nandmtd1_MarkNANDBlockBad(struct yaffs_DeviceStruct
*dev
, int blockNo
)
352 struct mtd_info
* mtd
= dev
->genericDevice
;
353 int blocksize
= dev
->nChunksPerBlock
* dev
->nDataBytesPerChunk
;
356 yaffs_trace(YAFFS_TRACE_BAD_BLOCKS
, "marking block %d bad", blockNo
);
358 retval
= mtd
->block_markbad(mtd
, (loff_t
)blocksize
* blockNo
);
359 return (retval
) ? YAFFS_FAIL
: YAFFS_OK
;
362 /* Check any MTD prerequists.
364 * Returns YAFFS_OK or YAFFS_FAIL.
366 static int nandmtd1_TestPrerequists(struct mtd_info
* mtd
)
368 /* 2.6.18 has mtd->ecclayout->oobavail */
369 /* 2.6.21 has mtd->ecclayout->oobavail and mtd->oobavail */
370 int oobavail
= mtd
->ecclayout
->oobavail
;
372 if (oobavail
< YTAG1_SIZE
) {
373 yaffs_trace(YAFFS_TRACE_ERROR
,
374 "mtd device has only %d bytes for tags, need %d",
375 oobavail
, YTAG1_SIZE
);
381 /* Query for the current state of a specific block.
383 * Examine the tags of the first chunk of the block and return the state:
384 * - YAFFS_BLOCK_STATE_DEAD, the block is marked bad
385 * - YAFFS_BLOCK_STATE_NEEDS_SCANNING, the block is in use
386 * - YAFFS_BLOCK_STATE_EMPTY, the block is clean
388 * Always returns YAFFS_OK.
390 int nandmtd1_QueryNANDBlock(struct yaffs_DeviceStruct
*dev
, int blockNo
,
391 yaffs_BlockState
* pState
, int *pSequenceNumber
)
393 struct mtd_info
* mtd
= dev
->genericDevice
;
394 int chunkNo
= blockNo
* dev
->nChunksPerBlock
;
395 yaffs_ExtendedTags etags
;
396 int state
= YAFFS_BLOCK_STATE_DEAD
;
400 /* We don't yet have a good place to test for MTD config prerequists.
401 * Do it here as we are called during the initial scan.
403 if (nandmtd1_TestPrerequists(mtd
) != YAFFS_OK
) {
407 retval
= nandmtd1_ReadChunkWithTagsFromNAND(dev
, chunkNo
, NULL
, &etags
);
408 if (etags
.blockBad
) {
409 yaffs_trace(YAFFS_TRACE_BAD_BLOCKS
,
410 "block %d is marked bad", blockNo
);
411 state
= YAFFS_BLOCK_STATE_DEAD
;
413 else if (etags
.chunkUsed
) {
414 state
= YAFFS_BLOCK_STATE_NEEDS_SCANNING
;
415 seqnum
= etags
.sequenceNumber
;
418 state
= YAFFS_BLOCK_STATE_EMPTY
;
422 *pSequenceNumber
= seqnum
;
424 /* query always succeeds */
428 #endif /*KERNEL_VERSION*/
430 --Boundary
-00=_5LbTGmt62YoutxM
--