yaffs_mtdif2.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. /*
  2. * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  3. *
  4. * Copyright (C) 2002-2007 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. /* mtd interface for YAFFS2 */
  14. /* XXX U-BOOT XXX */
  15. #include <common.h>
  16. #include "asm/errno.h"
  17. const char *yaffs_mtdif2_c_version =
  18. "$Id: yaffs_mtdif2.c,v 1.17 2007/02/14 01:09:06 wookey Exp $";
  19. #include "yportenv.h"
  20. #include "yaffs_mtdif2.h"
  21. #include "linux/mtd/mtd.h"
  22. #include "linux/types.h"
  23. #include "linux/time.h"
  24. #include "yaffs_packedtags2.h"
  25. int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND,
  26. const __u8 * data,
  27. const yaffs_ExtendedTags * tags)
  28. {
  29. struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
  30. #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
  31. struct mtd_oob_ops ops;
  32. #else
  33. size_t dummy;
  34. #endif
  35. int retval = 0;
  36. loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
  37. yaffs_PackedTags2 pt;
  38. T(YAFFS_TRACE_MTD,
  39. (TSTR
  40. ("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p"
  41. TENDSTR), chunkInNAND, data, tags));
  42. #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
  43. if (tags)
  44. yaffs_PackTags2(&pt, tags);
  45. else
  46. BUG(); /* both tags and data should always be present */
  47. if (data) {
  48. ops.mode = MTD_OOB_AUTO;
  49. ops.ooblen = sizeof(pt);
  50. ops.len = dev->nDataBytesPerChunk;
  51. ops.ooboffs = 0;
  52. ops.datbuf = (__u8 *)data;
  53. ops.oobbuf = (void *)&pt;
  54. retval = mtd->write_oob(mtd, addr, &ops);
  55. } else
  56. BUG(); /* both tags and data should always be present */
  57. #else
  58. if (tags) {
  59. yaffs_PackTags2(&pt, tags);
  60. }
  61. if (data && tags) {
  62. if (dev->useNANDECC)
  63. retval =
  64. mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,
  65. &dummy, data, (__u8 *) & pt, NULL);
  66. else
  67. retval =
  68. mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,
  69. &dummy, data, (__u8 *) & pt, NULL);
  70. } else {
  71. if (data)
  72. retval =
  73. mtd->write(mtd, addr, dev->nDataBytesPerChunk, &dummy,
  74. data);
  75. if (tags)
  76. retval =
  77. mtd->write_oob(mtd, addr, mtd->oobsize, &dummy,
  78. (__u8 *) & pt);
  79. }
  80. #endif
  81. if (retval == 0)
  82. return YAFFS_OK;
  83. else
  84. return YAFFS_FAIL;
  85. }
  86. int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,
  87. __u8 * data, yaffs_ExtendedTags * tags)
  88. {
  89. struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
  90. #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
  91. struct mtd_oob_ops ops;
  92. #endif
  93. size_t dummy;
  94. int retval = 0;
  95. loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
  96. yaffs_PackedTags2 pt;
  97. T(YAFFS_TRACE_MTD,
  98. (TSTR
  99. ("nandmtd2_ReadChunkWithTagsFromNAND chunk %d data %p tags %p"
  100. TENDSTR), chunkInNAND, data, tags));
  101. #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
  102. if (data && !tags)
  103. retval = mtd->read(mtd, addr, dev->nDataBytesPerChunk,
  104. &dummy, data);
  105. else if (tags) {
  106. ops.mode = MTD_OOB_AUTO;
  107. ops.ooblen = sizeof(pt);
  108. ops.len = data ? dev->nDataBytesPerChunk : sizeof(pt);
  109. ops.ooboffs = 0;
  110. ops.datbuf = data;
  111. ops.oobbuf = dev->spareBuffer;
  112. retval = mtd->read_oob(mtd, addr, &ops);
  113. }
  114. #else
  115. if (data && tags) {
  116. if (dev->useNANDECC) {
  117. retval =
  118. mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk,
  119. &dummy, data, dev->spareBuffer,
  120. NULL);
  121. } else {
  122. retval =
  123. mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk,
  124. &dummy, data, dev->spareBuffer,
  125. NULL);
  126. }
  127. } else {
  128. if (data)
  129. retval =
  130. mtd->read(mtd, addr, dev->nDataBytesPerChunk, &dummy,
  131. data);
  132. if (tags)
  133. retval =
  134. mtd->read_oob(mtd, addr, mtd->oobsize, &dummy,
  135. dev->spareBuffer);
  136. }
  137. #endif
  138. memcpy(&pt, dev->spareBuffer, sizeof(pt));
  139. if (tags)
  140. yaffs_UnpackTags2(tags, &pt);
  141. if(tags && retval == -EBADMSG && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR)
  142. tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;
  143. if (retval == 0)
  144. return YAFFS_OK;
  145. else
  146. return YAFFS_FAIL;
  147. }
  148. int nandmtd2_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo)
  149. {
  150. struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
  151. int retval;
  152. T(YAFFS_TRACE_MTD,
  153. (TSTR("nandmtd2_MarkNANDBlockBad %d" TENDSTR), blockNo));
  154. retval =
  155. mtd->block_markbad(mtd,
  156. blockNo * dev->nChunksPerBlock *
  157. dev->nDataBytesPerChunk);
  158. if (retval == 0)
  159. return YAFFS_OK;
  160. else
  161. return YAFFS_FAIL;
  162. }
  163. int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
  164. yaffs_BlockState * state, int *sequenceNumber)
  165. {
  166. struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
  167. int retval;
  168. T(YAFFS_TRACE_MTD,
  169. (TSTR("nandmtd2_QueryNANDBlock %d" TENDSTR), blockNo));
  170. retval =
  171. mtd->block_isbad(mtd,
  172. blockNo * dev->nChunksPerBlock *
  173. dev->nDataBytesPerChunk);
  174. if (retval) {
  175. T(YAFFS_TRACE_MTD, (TSTR("block is bad" TENDSTR)));
  176. *state = YAFFS_BLOCK_STATE_DEAD;
  177. *sequenceNumber = 0;
  178. } else {
  179. yaffs_ExtendedTags t;
  180. nandmtd2_ReadChunkWithTagsFromNAND(dev,
  181. blockNo *
  182. dev->nChunksPerBlock, NULL,
  183. &t);
  184. if (t.chunkUsed) {
  185. *sequenceNumber = t.sequenceNumber;
  186. *state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
  187. } else {
  188. *sequenceNumber = 0;
  189. *state = YAFFS_BLOCK_STATE_EMPTY;
  190. }
  191. }
  192. T(YAFFS_TRACE_MTD,
  193. (TSTR("block is bad seq %d state %d" TENDSTR), *sequenceNumber,
  194. *state));
  195. if (retval == 0)
  196. return YAFFS_OK;
  197. else
  198. return YAFFS_FAIL;
  199. }