Mercurial > yaffs-ecoscentric-gpl
comparison packages/fs/yaffs/current/src/patches/yaffs_mtdif2.c @ 425:dea4d7d250ad ecos
Move sources into packages/fs/yaffs/current/src/
| author | Ross Younger <wry@ecoscentric.com> |
|---|---|
| date | Fri, 14 May 2010 16:03:09 +0100 |
| parents | patches/yaffs_mtdif2.c@c6c9df8d8c26 |
| children |
comparison
equal
deleted
inserted
replaced
| 424:d21d6fd33e63 | 425:dea4d7d250ad |
|---|---|
| 1 /* | |
| 2 * YAFFS: Yet another FFS. A NAND-flash specific file system. | |
| 3 * | |
| 4 * Copyright (C) 2002 Aleph One Ltd. | |
| 5 * for Toby Churchill Ltd and Brightstar Engineering | |
| 6 * | |
| 7 * Created by Charles Manning <charles@aleph1.co.uk> | |
| 8 * | |
| 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. | |
| 12 */ | |
| 13 | |
| 14 /* mtd interface for YAFFS2 */ | |
| 15 | |
| 16 const char *yaffs_mtdif2_c_version = | |
| 17 "$Id: yaffs_mtdif2.c,v 1.2 2007-03-07 08:05:58 colin Exp $"; | |
| 18 | |
| 19 #include "yportenv.h" | |
| 20 | |
| 21 | |
| 22 #include "yaffs_mtdif2.h" | |
| 23 | |
| 24 #include "linux/mtd/mtd.h" | |
| 25 #include "linux/types.h" | |
| 26 #include "linux/time.h" | |
| 27 | |
| 28 #include "yaffs_packedtags2.h" | |
| 29 | |
| 30 | |
| 31 void nandmtd2_pt2buf(yaffs_Device *dev, yaffs_PackedTags2 *pt, int is_raw) | |
| 32 { | |
| 33 struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); | |
| 34 __u8 *ptab = (__u8 *)pt; /* packed tags as bytes */ | |
| 35 | |
| 36 int i, j = 0, k, n; | |
| 37 | |
| 38 /* Pack buffer with 0xff */ | |
| 39 for (i = 0; i < mtd->oobsize; i++) | |
| 40 dev->spareBuffer[i] = 0xff; | |
| 41 | |
| 42 if(!is_raw){ | |
| 43 memcpy(dev->spareBuffer,pt,sizeof(yaffs_PackedTags2)); | |
| 44 } else { | |
| 45 j = 0; | |
| 46 k = mtd->oobinfo.oobfree[j][0]; | |
| 47 n = mtd->oobinfo.oobfree[j][1]; | |
| 48 | |
| 49 if (n == 0) { | |
| 50 T(YAFFS_TRACE_ERROR, (TSTR("No OOB space for tags" TENDSTR))); | |
| 51 YBUG(); | |
| 52 } | |
| 53 | |
| 54 for (i = 0; i < sizeof(yaffs_PackedTags2); i++) { | |
| 55 if (n == 0) { | |
| 56 j++; | |
| 57 k = mtd->oobinfo.oobfree[j][0]; | |
| 58 n = mtd->oobinfo.oobfree[j][1]; | |
| 59 if (n == 0) { | |
| 60 T(YAFFS_TRACE_ERROR, (TSTR("No OOB space for tags" TENDSTR))); | |
| 61 YBUG(); | |
| 62 } | |
| 63 } | |
| 64 dev->spareBuffer[k] = ptab[i]; | |
| 65 k++; | |
| 66 n--; | |
| 67 } | |
| 68 } | |
| 69 | |
| 70 } | |
| 71 | |
| 72 void nandmtd2_buf2pt(yaffs_Device *dev, yaffs_PackedTags2 *pt, int is_raw) | |
| 73 { | |
| 74 struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); | |
| 75 int i, j = 0, k, n; | |
| 76 __u8 *ptab = (__u8 *)pt; /* packed tags as bytes */ | |
| 77 | |
| 78 | |
| 79 if (!is_raw) { | |
| 80 | |
| 81 memcpy(pt,dev->spareBuffer,sizeof(yaffs_PackedTags2)); | |
| 82 } else { | |
| 83 j = 0; | |
| 84 k = mtd->oobinfo.oobfree[j][0]; | |
| 85 n = mtd->oobinfo.oobfree[j][1]; | |
| 86 | |
| 87 if (n == 0) { | |
| 88 T(YAFFS_TRACE_ERROR, (TSTR("No space in OOB for tags" TENDSTR))); | |
| 89 YBUG(); | |
| 90 } | |
| 91 | |
| 92 for (i = 0; i < sizeof(yaffs_PackedTags2); i++) { | |
| 93 if (n == 0) { | |
| 94 j++; | |
| 95 k = mtd->oobinfo.oobfree[j][0]; | |
| 96 n = mtd->oobinfo.oobfree[j][1]; | |
| 97 if (n == 0) { | |
| 98 T(YAFFS_TRACE_ERROR, (TSTR("No space in OOB for tags" TENDSTR))); | |
| 99 YBUG(); | |
| 100 } | |
| 101 } | |
| 102 ptab[i] = dev->spareBuffer[k]; | |
| 103 k++; | |
| 104 n--; | |
| 105 } | |
| 106 } | |
| 107 | |
| 108 } | |
| 109 | |
| 110 int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND, | |
| 111 const __u8 * data, | |
| 112 const yaffs_ExtendedTags * tags) | |
| 113 { | |
| 114 struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); | |
| 115 size_t dummy; | |
| 116 int retval = 0; | |
| 117 | |
| 118 loff_t addr = ((loff_t) chunkInNAND) * dev->nBytesPerChunk; | |
| 119 | |
| 120 yaffs_PackedTags2 pt; | |
| 121 | |
| 122 T(YAFFS_TRACE_MTD, | |
| 123 (TSTR | |
| 124 ("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p" | |
| 125 TENDSTR), chunkInNAND, data, tags)); | |
| 126 | |
| 127 if (tags) { | |
| 128 yaffs_PackTags2(&pt, tags); | |
| 129 } | |
| 130 | |
| 131 if (data && tags) { | |
| 132 nandmtd2_pt2buf(dev, &pt, 0); | |
| 133 retval = | |
| 134 mtd->write_ecc(mtd, addr, dev->nBytesPerChunk, | |
| 135 &dummy, data, dev->spareBuffer, | |
| 136 NULL); | |
| 137 | |
| 138 } else { | |
| 139 | |
| 140 T(YAFFS_TRACE_ALWAYS, | |
| 141 (TSTR | |
| 142 ("Write chunk with null tags or data!" TENDSTR))); | |
| 143 YBUG(); | |
| 144 } | |
| 145 | |
| 146 if (retval == 0) | |
| 147 return YAFFS_OK; | |
| 148 else | |
| 149 return YAFFS_FAIL; | |
| 150 } | |
| 151 | |
| 152 int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND, | |
| 153 __u8 * data, yaffs_ExtendedTags * tags) | |
| 154 { | |
| 155 struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); | |
| 156 size_t dummy; | |
| 157 int retval = 0; | |
| 158 | |
| 159 loff_t addr = ((loff_t) chunkInNAND) * dev->nBytesPerChunk; | |
| 160 | |
| 161 yaffs_PackedTags2 pt; | |
| 162 | |
| 163 T(YAFFS_TRACE_MTD, | |
| 164 (TSTR | |
| 165 ("nandmtd2_ReadChunkWithTagsToNAND chunk %d data %p tags %p" | |
| 166 TENDSTR), chunkInNAND, data, tags)); | |
| 167 | |
| 168 if (0 && data && tags) { | |
| 169 retval = | |
| 170 mtd->read_ecc(mtd, addr, dev->nBytesPerChunk, | |
| 171 &dummy, data, dev->spareBuffer, | |
| 172 NULL); | |
| 173 nandmtd2_buf2pt(dev, &pt, 0); | |
| 174 } else { | |
| 175 if (data) | |
| 176 retval = | |
| 177 mtd->read(mtd, addr, dev->nBytesPerChunk, &dummy, | |
| 178 data); | |
| 179 if (tags) { | |
| 180 retval = | |
| 181 mtd->read_oob(mtd, addr, mtd->oobsize, &dummy, | |
| 182 dev->spareBuffer); | |
| 183 nandmtd2_buf2pt(dev, &pt, 1); | |
| 184 } | |
| 185 } | |
| 186 | |
| 187 if (tags) | |
| 188 yaffs_UnpackTags2(tags, &pt); | |
| 189 | |
| 190 if (retval == 0) | |
| 191 return YAFFS_OK; | |
| 192 else | |
| 193 return YAFFS_FAIL; | |
| 194 } | |
| 195 | |
| 196 int nandmtd2_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo) | |
| 197 { | |
| 198 struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); | |
| 199 int retval; | |
| 200 T(YAFFS_TRACE_MTD, | |
| 201 (TSTR("nandmtd2_MarkNANDBlockBad %d" TENDSTR), blockNo)); | |
| 202 | |
| 203 retval = | |
| 204 mtd->block_markbad(mtd, | |
| 205 blockNo * dev->nChunksPerBlock * | |
| 206 dev->nBytesPerChunk); | |
| 207 | |
| 208 if (retval == 0) | |
| 209 return YAFFS_OK; | |
| 210 else | |
| 211 return YAFFS_FAIL; | |
| 212 | |
| 213 } | |
| 214 | |
| 215 int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, | |
| 216 yaffs_BlockState * state, int *sequenceNumber) | |
| 217 { | |
| 218 struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); | |
| 219 int retval; | |
| 220 | |
| 221 T(YAFFS_TRACE_MTD, | |
| 222 (TSTR("nandmtd2_QueryNANDBlock %d" TENDSTR), blockNo)); | |
| 223 retval = | |
| 224 mtd->block_isbad(mtd, | |
| 225 blockNo * dev->nChunksPerBlock * | |
| 226 dev->nBytesPerChunk); | |
| 227 | |
| 228 if (retval) { | |
| 229 T(YAFFS_TRACE_MTD, (TSTR("block is bad" TENDSTR))); | |
| 230 | |
| 231 *state = YAFFS_BLOCK_STATE_DEAD; | |
| 232 *sequenceNumber = 0; | |
| 233 } else { | |
| 234 yaffs_ExtendedTags t; | |
| 235 nandmtd2_ReadChunkWithTagsFromNAND(dev, | |
| 236 blockNo * | |
| 237 dev->nChunksPerBlock, NULL, | |
| 238 &t); | |
| 239 | |
| 240 if (t.chunkUsed) { | |
| 241 *sequenceNumber = t.sequenceNumber; | |
| 242 *state = YAFFS_BLOCK_STATE_NEEDS_SCANNING; | |
| 243 } else { | |
| 244 *sequenceNumber = 0; | |
| 245 *state = YAFFS_BLOCK_STATE_EMPTY; | |
| 246 } | |
| 247 | |
| 248 T(YAFFS_TRACE_MTD, | |
| 249 (TSTR("block is OK seq %d state %d" TENDSTR), *sequenceNumber, | |
| 250 *state)); | |
| 251 } | |
| 252 | |
| 253 if (retval == 0) | |
| 254 return YAFFS_OK; | |
| 255 else | |
| 256 return YAFFS_FAIL; | |
| 257 } | |
| 258 |
