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 */
18 #include "asm/errno.h"
20 const char *yaffs_mtdif2_c_version
=
21 "$Id: yaffs_mtdif2.c,v 1.17 2007/02/14 01:09:06 wookey Exp $";
26 #include "yaffs_mtdif2.h"
28 #include "linux/mtd/mtd.h"
29 #include "linux/types.h"
30 #include "linux/time.h"
32 #include "yaffs_packedtags2.h"
34 int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device
* dev
, int chunkInNAND
,
36 const yaffs_ExtendedTags
* tags
)
38 struct mtd_info
*mtd
= (struct mtd_info
*)(dev
->genericDevice
);
39 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
40 struct mtd_oob_ops ops
;
46 loff_t addr
= ((loff_t
) chunkInNAND
) * dev
->nDataBytesPerChunk
;
52 ("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p"
53 TENDSTR
), chunkInNAND
, data
, tags
));
55 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
57 yaffs_PackTags2(&pt
, tags
);
59 BUG(); /* both tags and data should always be present */
62 ops
.mode
= MTD_OOB_AUTO
;
63 ops
.ooblen
= sizeof(pt
);
64 ops
.len
= dev
->nDataBytesPerChunk
;
66 ops
.datbuf
= (__u8
*)data
;
67 ops
.oobbuf
= (void *)&pt
;
68 retval
= mtd
->write_oob(mtd
, addr
, &ops
);
70 BUG(); /* both tags and data should always be present */
73 yaffs_PackTags2(&pt
, tags
);
79 mtd
->write_ecc(mtd
, addr
, dev
->nDataBytesPerChunk
,
80 &dummy
, data
, (__u8
*) & pt
, NULL
);
83 mtd
->write_ecc(mtd
, addr
, dev
->nDataBytesPerChunk
,
84 &dummy
, data
, (__u8
*) & pt
, NULL
);
88 mtd
->write(mtd
, addr
, dev
->nDataBytesPerChunk
, &dummy
,
92 mtd
->write_oob(mtd
, addr
, mtd
->oobsize
, &dummy
,
104 int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device
* dev
, int chunkInNAND
,
105 __u8
* data
, yaffs_ExtendedTags
* tags
)
107 struct mtd_info
*mtd
= (struct mtd_info
*)(dev
->genericDevice
);
108 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
109 struct mtd_oob_ops ops
;
114 loff_t addr
= ((loff_t
) chunkInNAND
) * dev
->nDataBytesPerChunk
;
116 yaffs_PackedTags2 pt
;
120 ("nandmtd2_ReadChunkWithTagsFromNAND chunk %d data %p tags %p"
121 TENDSTR
), chunkInNAND
, data
, tags
));
123 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
125 retval
= mtd
->read(mtd
, addr
, dev
->nDataBytesPerChunk
,
128 ops
.mode
= MTD_OOB_AUTO
;
129 ops
.ooblen
= sizeof(pt
);
130 ops
.len
= data
? dev
->nDataBytesPerChunk
: sizeof(pt
);
133 ops
.oobbuf
= dev
->spareBuffer
;
134 retval
= mtd
->read_oob(mtd
, addr
, &ops
);
138 if (dev
->useNANDECC
) {
140 mtd
->read_ecc(mtd
, addr
, dev
->nDataBytesPerChunk
,
141 &dummy
, data
, dev
->spareBuffer
,
145 mtd
->read_ecc(mtd
, addr
, dev
->nDataBytesPerChunk
,
146 &dummy
, data
, dev
->spareBuffer
,
152 mtd
->read(mtd
, addr
, dev
->nDataBytesPerChunk
, &dummy
,
156 mtd
->read_oob(mtd
, addr
, mtd
->oobsize
, &dummy
,
161 memcpy(&pt
, dev
->spareBuffer
, sizeof(pt
));
164 yaffs_UnpackTags2(tags
, &pt
);
166 if(tags
&& retval
== -EBADMSG
&& tags
->eccResult
== YAFFS_ECC_RESULT_NO_ERROR
)
167 tags
->eccResult
= YAFFS_ECC_RESULT_UNFIXED
;
175 int nandmtd2_MarkNANDBlockBad(struct yaffs_DeviceStruct
*dev
, int blockNo
)
177 struct mtd_info
*mtd
= (struct mtd_info
*)(dev
->genericDevice
);
180 (TSTR("nandmtd2_MarkNANDBlockBad %d" TENDSTR
), blockNo
));
183 mtd
->block_markbad(mtd
,
184 blockNo
* dev
->nChunksPerBlock
*
185 dev
->nDataBytesPerChunk
);
194 int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct
*dev
, int blockNo
,
195 yaffs_BlockState
* state
, int *sequenceNumber
)
197 struct mtd_info
*mtd
= (struct mtd_info
*)(dev
->genericDevice
);
201 (TSTR("nandmtd2_QueryNANDBlock %d" TENDSTR
), blockNo
));
203 mtd
->block_isbad(mtd
,
204 blockNo
* dev
->nChunksPerBlock
*
205 dev
->nDataBytesPerChunk
);
208 T(YAFFS_TRACE_MTD
, (TSTR("block is bad" TENDSTR
)));
210 *state
= YAFFS_BLOCK_STATE_DEAD
;
213 yaffs_ExtendedTags t
;
214 nandmtd2_ReadChunkWithTagsFromNAND(dev
,
216 dev
->nChunksPerBlock
, NULL
,
220 *sequenceNumber
= t
.sequenceNumber
;
221 *state
= YAFFS_BLOCK_STATE_NEEDS_SCANNING
;
224 *state
= YAFFS_BLOCK_STATE_EMPTY
;
228 (TSTR("block is bad seq %d state %d" TENDSTR
), *sequenceNumber
,