Mercurial > yaffs-ecoscentric-gpl
annotate yaffs_mtdif2.c @ 143:bec3d6bed11a
Interworking with 2.6.18 kernel enabled
Notable is that to enable it for yaffs1 compatibility mode, I introduced
a workaround (translate_spare2oob/translate_oob2spare) which should be
redesigned if possible. The thing is that yaffs1 presumes SmartMedia OOB
layout which might be not true for a lot of modern flash controllers, so
there has to be translation.
Or, in case we get to tags inband, this workaround will become useless.
| author | vwool <vwool> |
|---|---|
| date | Tue, 26 Sep 2006 13:28:13 +0000 |
| parents | 34ac1a735230 |
| children | 1a32267ef1c1 |
| rev | line source |
|---|---|
| 7 | 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 | |
| 76 | 16 /* mtd interface for YAFFS2 */ |
| 7 | 17 |
| 76 | 18 const char *yaffs_mtdif2_c_version = |
| 143 | 19 "$Id: yaffs_mtdif2.c,v 1.13 2006-09-26 13:28:13 vwool Exp $"; |
| 76 | 20 |
|
45
1f2f55618d63
If kernel/config.h is included in yportenv.h, then yportenv.h must be
marty <marty>
parents:
24
diff
changeset
|
21 #include "yportenv.h" |
| 7 | 22 |
| 23 | |
| 24 #include "yaffs_mtdif2.h" | |
| 25 | |
| 26 #include "linux/mtd/mtd.h" | |
| 27 #include "linux/types.h" | |
| 28 #include "linux/time.h" | |
| 29 | |
| 30 #include "yaffs_packedtags2.h" | |
| 31 | |
| 76 | 32 int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND, |
| 33 const __u8 * data, | |
| 34 const yaffs_ExtendedTags * tags) | |
| 7 | 35 { |
| 36 struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); | |
| 143 | 37 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) |
| 38 struct mtd_oob_ops ops; | |
| 39 #else | |
| 7 | 40 size_t dummy; |
| 143 | 41 #endif |
| 7 | 42 int retval = 0; |
| 43 | |
| 76 | 44 loff_t addr = ((loff_t) chunkInNAND) * dev->nBytesPerChunk; |
| 7 | 45 |
| 46 yaffs_PackedTags2 pt; | |
| 47 | |
| 76 | 48 T(YAFFS_TRACE_MTD, |
| 49 (TSTR | |
| 50 ("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p" | |
| 51 TENDSTR), chunkInNAND, data, tags)); | |
| 52 | |
| 143 | 53 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) |
| 54 if (tags) | |
| 55 yaffs_PackTags2(&pt, tags); | |
| 56 else | |
| 57 BUG(); /* both tags and data should always be present */ | |
| 58 | |
| 59 if (data) { | |
| 60 ops.mode = MTD_OOB_AUTO; | |
| 61 ops.ooblen = sizeof(pt); | |
| 62 ops.len = dev->nBytesPerChunk; | |
| 63 ops.ooboffs = 0; | |
| 64 ops.datbuf = (__u8 *)data; | |
| 65 ops.oobbuf = (void *)&pt; | |
| 66 retval = mtd->write_oob(mtd, addr, &ops); | |
| 67 } else | |
| 68 BUG(); /* both tags and data should always be present */ | |
| 69 #else | |
| 76 | 70 if (tags) { |
| 71 yaffs_PackTags2(&pt, tags); | |
| 7 | 72 } |
| 73 | |
| 76 | 74 if (data && tags) { |
| 75 if (dev->useNANDECC) | |
| 76 retval = | |
| 77 mtd->write_ecc(mtd, addr, dev->nBytesPerChunk, | |
| 78 &dummy, data, (__u8 *) & pt, NULL); | |
| 7 | 79 else |
| 76 | 80 retval = |
| 81 mtd->write_ecc(mtd, addr, dev->nBytesPerChunk, | |
| 82 &dummy, data, (__u8 *) & pt, NULL); | |
| 83 } else { | |
| 84 if (data) | |
| 85 retval = | |
| 86 mtd->write(mtd, addr, dev->nBytesPerChunk, &dummy, | |
| 87 data); | |
| 88 if (tags) | |
| 89 retval = | |
| 90 mtd->write_oob(mtd, addr, mtd->oobsize, &dummy, | |
| 91 (__u8 *) & pt); | |
| 92 | |
| 7 | 93 } |
| 143 | 94 #endif |
| 7 | 95 |
| 76 | 96 if (retval == 0) |
| 97 return YAFFS_OK; | |
| 98 else | |
| 99 return YAFFS_FAIL; | |
| 7 | 100 } |
| 101 | |
| 76 | 102 int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND, |
| 103 __u8 * data, yaffs_ExtendedTags * tags) | |
| 7 | 104 { |
| 105 struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); | |
| 143 | 106 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) |
| 107 struct mtd_oob_ops ops; | |
| 108 #endif | |
| 7 | 109 size_t dummy; |
| 76 | 110 int retval = 0; |
| 7 | 111 |
| 76 | 112 loff_t addr = ((loff_t) chunkInNAND) * dev->nBytesPerChunk; |
| 113 | |
| 7 | 114 yaffs_PackedTags2 pt; |
| 115 | |
| 76 | 116 T(YAFFS_TRACE_MTD, |
| 117 (TSTR | |
|
126
2e7fd6d40037
Fix a couple of mistakes in TRACE/Error messages. Update copyright date.
wookey <wookey>
parents:
103
diff
changeset
|
118 ("nandmtd2_ReadChunkWithTagsFromNAND chunk %d data %p tags %p" |
| 76 | 119 TENDSTR), chunkInNAND, data, tags)); |
| 7 | 120 |
| 143 | 121 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) |
| 122 if (data && !tags) | |
| 123 retval = mtd->read(mtd, addr, dev->nBytesPerChunk, | |
| 124 &dummy, data); | |
| 125 else if (tags) { | |
| 126 ops.mode = MTD_OOB_AUTO; | |
| 127 ops.ooblen = sizeof(pt); | |
| 128 ops.len = data ? dev->nBytesPerChunk : sizeof(pt); | |
| 129 ops.ooboffs = 0; | |
| 130 ops.datbuf = data; | |
| 131 ops.oobbuf = dev->spareBuffer; | |
| 132 retval = mtd->read_oob(mtd, addr, &ops); | |
| 133 } | |
| 134 #else | |
| 103 | 135 if (data && tags) { |
| 76 | 136 if (dev->useNANDECC) { |
| 137 retval = | |
| 138 mtd->read_ecc(mtd, addr, dev->nBytesPerChunk, | |
| 139 &dummy, data, dev->spareBuffer, | |
| 140 NULL); | |
| 141 } else { | |
| 142 retval = | |
| 143 mtd->read_ecc(mtd, addr, dev->nBytesPerChunk, | |
| 144 &dummy, data, dev->spareBuffer, | |
| 145 NULL); | |
| 7 | 146 } |
| 76 | 147 } else { |
| 148 if (data) | |
| 149 retval = | |
| 150 mtd->read(mtd, addr, dev->nBytesPerChunk, &dummy, | |
| 151 data); | |
| 152 if (tags) | |
| 153 retval = | |
| 154 mtd->read_oob(mtd, addr, mtd->oobsize, &dummy, | |
| 155 dev->spareBuffer); | |
| 7 | 156 } |
| 143 | 157 #endif |
| 7 | 158 |
| 76 | 159 memcpy(&pt, dev->spareBuffer, sizeof(pt)); |
| 160 | |
| 161 if (tags) | |
| 162 yaffs_UnpackTags2(tags, &pt); | |
| 142 | 163 |
| 164 if(tags && retval == -EBADMSG && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR) | |
| 165 tags->eccResult = YAFFS_ECC_RESULT_UNFIXED; | |
| 76 | 166 |
| 167 if (retval == 0) | |
| 168 return YAFFS_OK; | |
| 169 else | |
| 170 return YAFFS_FAIL; | |
| 7 | 171 } |
| 172 | |
| 173 int nandmtd2_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo) | |
| 174 { | |
| 175 struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); | |
| 176 int retval; | |
| 76 | 177 T(YAFFS_TRACE_MTD, |
| 178 (TSTR("nandmtd2_MarkNANDBlockBad %d" TENDSTR), blockNo)); | |
| 7 | 179 |
| 76 | 180 retval = |
| 181 mtd->block_markbad(mtd, | |
| 182 blockNo * dev->nChunksPerBlock * | |
| 183 dev->nBytesPerChunk); | |
| 184 | |
| 185 if (retval == 0) | |
| 186 return YAFFS_OK; | |
| 187 else | |
| 188 return YAFFS_FAIL; | |
| 7 | 189 |
| 190 } | |
| 191 | |
| 76 | 192 int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, |
| 193 yaffs_BlockState * state, int *sequenceNumber) | |
| 7 | 194 { |
| 195 struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); | |
| 196 int retval; | |
| 76 | 197 |
| 198 T(YAFFS_TRACE_MTD, | |
| 199 (TSTR("nandmtd2_QueryNANDBlock %d" TENDSTR), blockNo)); | |
| 200 retval = | |
| 201 mtd->block_isbad(mtd, | |
| 202 blockNo * dev->nChunksPerBlock * | |
| 203 dev->nBytesPerChunk); | |
| 204 | |
| 205 if (retval) { | |
| 206 T(YAFFS_TRACE_MTD, (TSTR("block is bad" TENDSTR))); | |
| 207 | |
| 7 | 208 *state = YAFFS_BLOCK_STATE_DEAD; |
| 209 *sequenceNumber = 0; | |
| 76 | 210 } else { |
| 7 | 211 yaffs_ExtendedTags t; |
| 76 | 212 nandmtd2_ReadChunkWithTagsFromNAND(dev, |
| 213 blockNo * | |
| 214 dev->nChunksPerBlock, NULL, | |
| 215 &t); | |
| 216 | |
| 217 if (t.chunkUsed) { | |
| 218 *sequenceNumber = t.sequenceNumber; | |
| 219 *state = YAFFS_BLOCK_STATE_NEEDS_SCANNING; | |
| 220 } else { | |
| 221 *sequenceNumber = 0; | |
| 222 *state = YAFFS_BLOCK_STATE_EMPTY; | |
| 7 | 223 } |
| 224 } | |
| 76 | 225 T(YAFFS_TRACE_MTD, |
| 226 (TSTR("block is bad seq %d state %d" TENDSTR), *sequenceNumber, | |
| 227 *state)); | |
| 7 | 228 |
| 76 | 229 if (retval == 0) |
| 230 return YAFFS_OK; | |
| 231 else | |
| 232 return YAFFS_FAIL; | |
| 7 | 233 } |
| 234 |
