Add support for faster yaffs direct look-ups. Fix rename over problem
[yaffs2.git] / yaffs_mtdif2.c
1 /*
2  * YAFFS: Yet another FFS. A NAND-flash specific file system. 
3  * yaffs_mtdif.c  NAND mtd wrapper functions.
4  *
5  * Copyright (C) 2002 Aleph One Ltd.
6  *   for Toby Churchill Ltd and Brightstar Engineering
7  *
8  * Created by Charles Manning <charles@aleph1.co.uk>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2 as
12  * published by the Free Software Foundation.
13  *
14  */
15
16 /* mtd interface for YAFFS2 */
17
18 const char *yaffs_mtdif2_c_version =
19     "$Id: yaffs_mtdif2.c,v 1.7 2005-08-11 01:07:43 marty Exp $";
20
21 #include "yportenv.h"
22
23 #ifdef CONFIG_YAFFS_YAFFS1
24
25 #include "yaffs_mtdif2.h"
26
27 #include "linux/mtd/mtd.h"
28 #include "linux/types.h"
29 #include "linux/time.h"
30
31 #include "yaffs_packedtags2.h"
32
33 int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND,
34                                       const __u8 * data,
35                                       const yaffs_ExtendedTags * tags)
36 {
37         struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
38         size_t dummy;
39         int retval = 0;
40
41         loff_t addr = ((loff_t) chunkInNAND) * dev->nBytesPerChunk;
42
43         yaffs_PackedTags2 pt;
44
45         T(YAFFS_TRACE_MTD,
46           (TSTR
47            ("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p"
48             TENDSTR), chunkInNAND, data, tags));
49
50         if (tags) {
51                 yaffs_PackTags2(&pt, tags);
52         }
53
54         if (data && tags) {
55                 if (dev->useNANDECC)
56                         retval =
57                             mtd->write_ecc(mtd, addr, dev->nBytesPerChunk,
58                                            &dummy, data, (__u8 *) & pt, NULL);
59                 else
60                         retval =
61                             mtd->write_ecc(mtd, addr, dev->nBytesPerChunk,
62                                            &dummy, data, (__u8 *) & pt, NULL);
63         } else {
64                 if (data)
65                         retval =
66                             mtd->write(mtd, addr, dev->nBytesPerChunk, &dummy,
67                                        data);
68                 if (tags)
69                         retval =
70                             mtd->write_oob(mtd, addr, mtd->oobsize, &dummy,
71                                            (__u8 *) & pt);
72
73         }
74
75         if (retval == 0)
76                 return YAFFS_OK;
77         else
78                 return YAFFS_FAIL;
79 }
80
81 int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,
82                                        __u8 * data, yaffs_ExtendedTags * tags)
83 {
84         struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
85         size_t dummy;
86         int retval = 0;
87
88         loff_t addr = ((loff_t) chunkInNAND) * dev->nBytesPerChunk;
89
90         yaffs_PackedTags2 pt;
91
92         T(YAFFS_TRACE_MTD,
93           (TSTR
94            ("nandmtd2_ReadChunkWithTagsToNAND chunk %d data %p tags %p"
95             TENDSTR), chunkInNAND, data, tags));
96
97         if (data && tags) {
98                 if (dev->useNANDECC) {
99                         retval =
100                             mtd->read_ecc(mtd, addr, dev->nBytesPerChunk,
101                                           &dummy, data, dev->spareBuffer,
102                                           NULL);
103                 } else {
104                         retval =
105                             mtd->read_ecc(mtd, addr, dev->nBytesPerChunk,
106                                           &dummy, data, dev->spareBuffer,
107                                           NULL);
108                 }
109         } else {
110                 if (data)
111                         retval =
112                             mtd->read(mtd, addr, dev->nBytesPerChunk, &dummy,
113                                       data);
114                 if (tags)
115                         retval =
116                             mtd->read_oob(mtd, addr, mtd->oobsize, &dummy,
117                                           dev->spareBuffer);
118         }
119
120         memcpy(&pt, dev->spareBuffer, sizeof(pt));
121
122         if (tags)
123                 yaffs_UnpackTags2(tags, &pt);
124
125         if (retval == 0)
126                 return YAFFS_OK;
127         else
128                 return YAFFS_FAIL;
129 }
130
131 int nandmtd2_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo)
132 {
133         struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
134         int retval;
135         T(YAFFS_TRACE_MTD,
136           (TSTR("nandmtd2_MarkNANDBlockBad %d" TENDSTR), blockNo));
137
138         retval =
139             mtd->block_markbad(mtd,
140                                blockNo * dev->nChunksPerBlock *
141                                dev->nBytesPerChunk);
142
143         if (retval == 0)
144                 return YAFFS_OK;
145         else
146                 return YAFFS_FAIL;
147
148 }
149
150 int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
151                             yaffs_BlockState * state, int *sequenceNumber)
152 {
153         struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
154         int retval;
155
156         T(YAFFS_TRACE_MTD,
157           (TSTR("nandmtd2_QueryNANDBlock %d" TENDSTR), blockNo));
158         retval =
159             mtd->block_isbad(mtd,
160                              blockNo * dev->nChunksPerBlock *
161                              dev->nBytesPerChunk);
162
163         if (retval) {
164                 T(YAFFS_TRACE_MTD, (TSTR("block is bad" TENDSTR)));
165
166                 *state = YAFFS_BLOCK_STATE_DEAD;
167                 *sequenceNumber = 0;
168         } else {
169                 yaffs_ExtendedTags t;
170                 nandmtd2_ReadChunkWithTagsFromNAND(dev,
171                                                    blockNo *
172                                                    dev->nChunksPerBlock, NULL,
173                                                    &t);
174
175                 if (t.chunkUsed) {
176                         *sequenceNumber = t.sequenceNumber;
177                         *state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
178                 } else {
179                         *sequenceNumber = 0;
180                         *state = YAFFS_BLOCK_STATE_EMPTY;
181                 }
182         }
183         T(YAFFS_TRACE_MTD,
184           (TSTR("block is bad seq %d state %d" TENDSTR), *sequenceNumber,
185            *state));
186
187         if (retval == 0)
188                 return YAFFS_OK;
189         else
190                 return YAFFS_FAIL;
191 }
192
193 #endif