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
=
21 #include "yaffs_mtdif2.h"
23 #include "linux/mtd/mtd.h"
24 #include "linux/types.h"
25 #include "linux/time.h"
27 #include "yaffs_packedtags2.h"
29 int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device
* dev
, int chunkInNAND
,
31 const yaffs_ExtendedTags
* tags
)
33 struct mtd_info
*mtd
= (struct mtd_info
*)(dev
->genericDevice
);
34 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
35 struct mtd_oob_ops ops
;
41 loff_t addr
= ((loff_t
) chunkInNAND
) * dev
->nDataBytesPerChunk
;
47 ("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p"
48 TENDSTR
), chunkInNAND
, data
, tags
));
50 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
52 yaffs_PackTags2(&pt
, tags
);
54 BUG(); /* both tags and data should always be present */
57 ops
.mode
= MTD_OOB_AUTO
;
58 ops
.ooblen
= sizeof(pt
);
59 ops
.len
= dev
->nDataBytesPerChunk
;
61 ops
.datbuf
= (__u8
*)data
;
62 ops
.oobbuf
= (void *)&pt
;
63 retval
= mtd
->write_oob(mtd
, addr
, &ops
);
65 BUG(); /* both tags and data should always be present */
68 yaffs_PackTags2(&pt
, tags
);
74 mtd
->write_ecc(mtd
, addr
, dev
->nDataBytesPerChunk
,
75 &dummy
, data
, (__u8
*) & pt
, NULL
);
78 mtd
->write_ecc(mtd
, addr
, dev
->nDataBytesPerChunk
,
79 &dummy
, data
, (__u8
*) & pt
, NULL
);
83 mtd
->write(mtd
, addr
, dev
->nDataBytesPerChunk
, &dummy
,
87 mtd
->write_oob(mtd
, addr
, mtd
->oobsize
, &dummy
,
99 int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device
* dev
, int chunkInNAND
,
100 __u8
* data
, yaffs_ExtendedTags
* tags
)
102 struct mtd_info
*mtd
= (struct mtd_info
*)(dev
->genericDevice
);
103 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
104 struct mtd_oob_ops ops
;
109 loff_t addr
= ((loff_t
) chunkInNAND
) * dev
->nDataBytesPerChunk
;
111 yaffs_PackedTags2 pt
;
115 ("nandmtd2_ReadChunkWithTagsFromNAND chunk %d data %p tags %p"
116 TENDSTR
), chunkInNAND
, data
, tags
));
118 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
120 retval
= mtd
->read(mtd
, addr
, dev
->nDataBytesPerChunk
,
123 ops
.mode
= MTD_OOB_AUTO
;
124 ops
.ooblen
= sizeof(pt
);
125 ops
.len
= data
? dev
->nDataBytesPerChunk
: sizeof(pt
);
128 ops
.oobbuf
= dev
->spareBuffer
;
129 retval
= mtd
->read_oob(mtd
, addr
, &ops
);
133 if (dev
->useNANDECC
) {
135 mtd
->read_ecc(mtd
, addr
, dev
->nDataBytesPerChunk
,
136 &dummy
, data
, dev
->spareBuffer
,
140 mtd
->read_ecc(mtd
, addr
, dev
->nDataBytesPerChunk
,
141 &dummy
, data
, dev
->spareBuffer
,
147 mtd
->read(mtd
, addr
, dev
->nDataBytesPerChunk
, &dummy
,
151 mtd
->read_oob(mtd
, addr
, mtd
->oobsize
, &dummy
,
156 memcpy(&pt
, dev
->spareBuffer
, sizeof(pt
));
159 yaffs_UnpackTags2(tags
, &pt
);
161 if(tags
&& retval
== -EBADMSG
&& tags
->eccResult
== YAFFS_ECC_RESULT_NO_ERROR
)
162 tags
->eccResult
= YAFFS_ECC_RESULT_UNFIXED
;
170 int nandmtd2_MarkNANDBlockBad(struct yaffs_DeviceStruct
*dev
, int blockNo
)
172 struct mtd_info
*mtd
= (struct mtd_info
*)(dev
->genericDevice
);
175 (TSTR("nandmtd2_MarkNANDBlockBad %d" TENDSTR
), blockNo
));
178 mtd
->block_markbad(mtd
,
179 blockNo
* dev
->nChunksPerBlock
*
180 dev
->nDataBytesPerChunk
);
189 int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct
*dev
, int blockNo
,
190 yaffs_BlockState
* state
, int *sequenceNumber
)
192 struct mtd_info
*mtd
= (struct mtd_info
*)(dev
->genericDevice
);
196 (TSTR("nandmtd2_QueryNANDBlock %d" TENDSTR
), blockNo
));
198 mtd
->block_isbad(mtd
,
199 blockNo
* dev
->nChunksPerBlock
*
200 dev
->nDataBytesPerChunk
);
203 T(YAFFS_TRACE_MTD
, (TSTR("block is bad" TENDSTR
)));
205 *state
= YAFFS_BLOCK_STATE_DEAD
;
208 yaffs_ExtendedTags t
;
209 nandmtd2_ReadChunkWithTagsFromNAND(dev
,
211 dev
->nChunksPerBlock
, NULL
,
215 *sequenceNumber
= t
.sequenceNumber
;
216 *state
= YAFFS_BLOCK_STATE_NEEDS_SCANNING
;
219 *state
= YAFFS_BLOCK_STATE_EMPTY
;
223 (TSTR("block is bad seq %d state %d" TENDSTR
), *sequenceNumber
,