2 * YAFFS: Yet another FFS. A NAND-flash specific file system.
4 * Copyright (C) 2002-2018 Aleph One Ltd.
6 * Created by Charles Manning <charles@aleph1.co.uk>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
13 /* mtd interface for YAFFS2 */
15 const char *yaffs_mtdif2_c_version =
16 "$Id: yaffs_mtdif2.c,v 1.2 2007-03-07 08:05:58 colin Exp $";
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"
30 void nandmtd2_pt2buf(struct yaffs_dev *dev, yaffs_PackedTags2 *pt, int is_raw)
32 struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
33 u8 *ptab = (u8 *)pt; /* packed tags as bytes */
37 /* Pack buffer with 0xff */
38 for (i = 0; i < mtd->oobsize; i++)
39 dev->spareBuffer[i] = 0xff;
42 memcpy(dev->spareBuffer,pt,sizeof(yaffs_PackedTags2));
45 k = mtd->oobinfo.oobfree[j][0];
46 n = mtd->oobinfo.oobfree[j][1];
49 T(YAFFS_TRACE_ERROR, (TSTR("No OOB space for tags" TENDSTR)));
53 for (i = 0; i < sizeof(yaffs_PackedTags2); i++) {
56 k = mtd->oobinfo.oobfree[j][0];
57 n = mtd->oobinfo.oobfree[j][1];
59 T(YAFFS_TRACE_ERROR, (TSTR("No OOB space for tags" TENDSTR)));
63 dev->spareBuffer[k] = ptab[i];
71 void nandmtd2_buf2pt(struct yaffs_dev *dev, yaffs_PackedTags2 *pt, int is_raw)
73 struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
75 u8 *ptab = (u8 *)pt; /* packed tags as bytes */
80 memcpy(pt,dev->spareBuffer,sizeof(yaffs_PackedTags2));
83 k = mtd->oobinfo.oobfree[j][0];
84 n = mtd->oobinfo.oobfree[j][1];
87 T(YAFFS_TRACE_ERROR, (TSTR("No space in OOB for tags" TENDSTR)));
91 for (i = 0; i < sizeof(yaffs_PackedTags2); i++) {
94 k = mtd->oobinfo.oobfree[j][0];
95 n = mtd->oobinfo.oobfree[j][1];
97 T(YAFFS_TRACE_ERROR, (TSTR("No space in OOB for tags" TENDSTR)));
101 ptab[i] = dev->spareBuffer[k];
109 int nandmtd2_WriteChunkWithTagsToNAND(struct yaffs_dev * dev, int nand_chunk,
111 const struct yaffs_ext_tags * tags)
113 struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
117 loff_t addr = ((loff_t) nand_chunk) * dev->n_bytesPerChunk;
119 yaffs_PackedTags2 pt;
123 ("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p"
124 TENDSTR), nand_chunk, data, tags));
127 yaffs_PackTags2(&pt, tags);
131 nandmtd2_pt2buf(dev, &pt, 0);
133 mtd->write_ecc(mtd, addr, dev->n_bytesPerChunk,
134 &dummy, data, dev->spareBuffer,
139 T(YAFFS_TRACE_ALWAYS,
141 ("Write chunk with null tags or data!" TENDSTR)));
151 int nandmtd2_ReadChunkWithTagsFromNAND(struct yaffs_dev * dev, int nand_chunk,
152 u8 * data, struct yaffs_ext_tags * tags)
154 struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
158 loff_t addr = ((loff_t) nand_chunk) * dev->n_bytesPerChunk;
160 yaffs_PackedTags2 pt;
164 ("nandmtd2_ReadChunkWithTagsToNAND chunk %d data %p tags %p"
165 TENDSTR), nand_chunk, data, tags));
167 if (0 && data && tags) {
169 mtd->read_ecc(mtd, addr, dev->n_bytesPerChunk,
170 &dummy, data, dev->spareBuffer,
172 nandmtd2_buf2pt(dev, &pt, 0);
176 mtd->read(mtd, addr, dev->n_bytesPerChunk, &dummy,
180 mtd->read_oob(mtd, addr, mtd->oobsize, &dummy,
182 nandmtd2_buf2pt(dev, &pt, 1);
187 yaffs_unpack_tags2(tags, &pt);
195 int nandmtd2_MarkNANDBlockBad(struct yaffs_dev *dev, int block_no)
197 struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
200 (TSTR("nandmtd2_MarkNANDBlockBad %d" TENDSTR), block_no));
203 mtd->block_markbad(mtd,
204 block_no * dev->chunks_per_block *
205 dev->n_bytesPerChunk);
214 int nandmtd2_QueryNANDBlock(struct yaffs_dev *dev, int block_no,
215 enum yaffs_block_state * state, int *seq_number)
217 struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
221 (TSTR("nandmtd2_QueryNANDBlock %d" TENDSTR), block_no));
223 mtd->block_isbad(mtd,
224 block_no * dev->chunks_per_block *
225 dev->n_bytesPerChunk);
228 T(YAFFS_TRACE_MTD, (TSTR("block is bad" TENDSTR)));
230 *state = YAFFS_BLOCK_STATE_DEAD;
233 struct yaffs_ext_tags t;
234 nandmtd2_ReadChunkWithTagsFromNAND(dev,
236 dev->chunks_per_block, NULL,
240 *seq_number = t.seq_number;
241 *state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
244 *state = YAFFS_BLOCK_STATE_EMPTY;
248 (TSTR("block is OK seq %d state %d" TENDSTR), *seq_number,