2 * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
4 * Copyright (C) 2002-2007 Aleph One Ltd.
5 * for Toby Churchill Ltd and Brightstar Engineering
7 * Created by Charles Manning <charles@aleph1.co.uk>
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.
14 /* mtd interface for YAFFS2 */
16 const char *yaffs_mtdif2_c_version
=
17 "$Id: yaffs_mtdif2.c,v 1.17 2007-02-14 01:09:06 wookey Exp $";
22 #include "yaffs_mtdif2.h"
24 #include "linux/mtd/mtd.h"
25 #include "linux/types.h"
26 #include "linux/time.h"
28 #include "yaffs_packedtags2.h"
30 int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device
* dev
, int chunkInNAND
,
32 const yaffs_ExtendedTags
* tags
)
34 struct mtd_info
*mtd
= (struct mtd_info
*)(dev
->genericDevice
);
35 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
36 struct mtd_oob_ops ops
;
42 loff_t addr
= ((loff_t
) chunkInNAND
) * dev
->nDataBytesPerChunk
;
48 ("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p"
49 TENDSTR
), chunkInNAND
, data
, tags
));
51 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
53 yaffs_PackTags2(&pt
, tags
);
55 BUG(); /* both tags and data should always be present */
58 ops
.mode
= MTD_OOB_AUTO
;
59 ops
.ooblen
= sizeof(pt
);
60 ops
.len
= dev
->nDataBytesPerChunk
;
62 ops
.datbuf
= (__u8
*)data
;
63 ops
.oobbuf
= (void *)&pt
;
64 retval
= mtd
->write_oob(mtd
, addr
, &ops
);
66 BUG(); /* both tags and data should always be present */
69 yaffs_PackTags2(&pt
, tags
);
75 mtd
->write_ecc(mtd
, addr
, dev
->nDataBytesPerChunk
,
76 &dummy
, data
, (__u8
*) & pt
, NULL
);
79 mtd
->write_ecc(mtd
, addr
, dev
->nDataBytesPerChunk
,
80 &dummy
, data
, (__u8
*) & pt
, NULL
);
84 mtd
->write(mtd
, addr
, dev
->nDataBytesPerChunk
, &dummy
,
88 mtd
->write_oob(mtd
, addr
, mtd
->oobsize
, &dummy
,
100 int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device
* dev
, int chunkInNAND
,
101 __u8
* data
, yaffs_ExtendedTags
* tags
)
103 struct mtd_info
*mtd
= (struct mtd_info
*)(dev
->genericDevice
);
104 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
105 struct mtd_oob_ops ops
;
110 loff_t addr
= ((loff_t
) chunkInNAND
) * dev
->nDataBytesPerChunk
;
112 yaffs_PackedTags2 pt
;
116 ("nandmtd2_ReadChunkWithTagsFromNAND chunk %d data %p tags %p"
117 TENDSTR
), chunkInNAND
, data
, tags
));
119 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
121 retval
= mtd
->read(mtd
, addr
, dev
->nDataBytesPerChunk
,
124 ops
.mode
= MTD_OOB_AUTO
;
125 ops
.ooblen
= sizeof(pt
);
126 ops
.len
= data
? dev
->nDataBytesPerChunk
: sizeof(pt
);
129 ops
.oobbuf
= dev
->spareBuffer
;
130 retval
= mtd
->read_oob(mtd
, addr
, &ops
);
134 if (dev
->useNANDECC
) {
136 mtd
->read_ecc(mtd
, addr
, dev
->nDataBytesPerChunk
,
137 &dummy
, data
, dev
->spareBuffer
,
141 mtd
->read_ecc(mtd
, addr
, dev
->nDataBytesPerChunk
,
142 &dummy
, data
, dev
->spareBuffer
,
148 mtd
->read(mtd
, addr
, dev
->nDataBytesPerChunk
, &dummy
,
152 mtd
->read_oob(mtd
, addr
, mtd
->oobsize
, &dummy
,
157 memcpy(&pt
, dev
->spareBuffer
, sizeof(pt
));
160 yaffs_UnpackTags2(tags
, &pt
);
162 if(tags
&& retval
== -EBADMSG
&& tags
->eccResult
== YAFFS_ECC_RESULT_NO_ERROR
)
163 tags
->eccResult
= YAFFS_ECC_RESULT_UNFIXED
;
171 int nandmtd2_MarkNANDBlockBad(struct yaffs_DeviceStruct
*dev
, int blockNo
)
173 struct mtd_info
*mtd
= (struct mtd_info
*)(dev
->genericDevice
);
176 (TSTR("nandmtd2_MarkNANDBlockBad %d" TENDSTR
), blockNo
));
179 mtd
->block_markbad(mtd
,
180 blockNo
* dev
->nChunksPerBlock
*
181 dev
->nDataBytesPerChunk
);
190 int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct
*dev
, int blockNo
,
191 yaffs_BlockState
* state
, int *sequenceNumber
)
193 struct mtd_info
*mtd
= (struct mtd_info
*)(dev
->genericDevice
);
197 (TSTR("nandmtd2_QueryNANDBlock %d" TENDSTR
), blockNo
));
199 mtd
->block_isbad(mtd
,
200 blockNo
* dev
->nChunksPerBlock
*
201 dev
->nDataBytesPerChunk
);
204 T(YAFFS_TRACE_MTD
, (TSTR("block is bad" TENDSTR
)));
206 *state
= YAFFS_BLOCK_STATE_DEAD
;
209 yaffs_ExtendedTags t
;
210 nandmtd2_ReadChunkWithTagsFromNAND(dev
,
212 dev
->nChunksPerBlock
, NULL
,
216 *sequenceNumber
= t
.sequenceNumber
;
217 *state
= YAFFS_BLOCK_STATE_NEEDS_SCANNING
;
220 *state
= YAFFS_BLOCK_STATE_EMPTY
;
224 (TSTR("block is bad seq %d state %d" TENDSTR
), *sequenceNumber
,