yaffs_nand.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. /*
  2. * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  3. *
  4. * Copyright (C) 2002-2010 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. #include "yaffs_trace.h"
  14. #include "yaffs_nand.h"
  15. #include "yaffs_tagscompat.h"
  16. #include "yaffs_tagsvalidity.h"
  17. #include "yaffs_getblockinfo.h"
  18. int yaffs_rd_chunk_tags_nand(struct yaffs_dev *dev, int nand_chunk,
  19. u8 *buffer, struct yaffs_ext_tags *tags)
  20. {
  21. int result;
  22. struct yaffs_ext_tags local_tags;
  23. int realigned_chunk = nand_chunk - dev->chunk_offset;
  24. dev->n_page_reads++;
  25. /* If there are no tags provided, use local tags to get prioritised gc working */
  26. if (!tags)
  27. tags = &local_tags;
  28. if (dev->param.read_chunk_tags_fn)
  29. result =
  30. dev->param.read_chunk_tags_fn(dev, realigned_chunk, buffer,
  31. tags);
  32. else
  33. result = yaffs_tags_compat_rd(dev,
  34. realigned_chunk, buffer, tags);
  35. if (tags && tags->ecc_result > YAFFS_ECC_RESULT_NO_ERROR) {
  36. struct yaffs_block_info *bi;
  37. bi = yaffs_get_block_info(dev,
  38. nand_chunk /
  39. dev->param.chunks_per_block);
  40. yaffs_handle_chunk_error(dev, bi);
  41. }
  42. return result;
  43. }
  44. int yaffs_wr_chunk_tags_nand(struct yaffs_dev *dev,
  45. int nand_chunk,
  46. const u8 *buffer, struct yaffs_ext_tags *tags)
  47. {
  48. dev->n_page_writes++;
  49. nand_chunk -= dev->chunk_offset;
  50. if (tags) {
  51. tags->seq_number = dev->seq_number;
  52. tags->chunk_used = 1;
  53. if (!yaffs_validate_tags(tags)) {
  54. yaffs_trace(YAFFS_TRACE_ERROR, "Writing uninitialised tags");
  55. YBUG();
  56. }
  57. yaffs_trace(YAFFS_TRACE_WRITE,
  58. "Writing chunk %d tags %d %d",
  59. nand_chunk, tags->obj_id, tags->chunk_id);
  60. } else {
  61. yaffs_trace(YAFFS_TRACE_ERROR, "Writing with no tags");
  62. YBUG();
  63. }
  64. if (dev->param.write_chunk_tags_fn)
  65. return dev->param.write_chunk_tags_fn(dev, nand_chunk, buffer,
  66. tags);
  67. else
  68. return yaffs_tags_compat_wr(dev, nand_chunk, buffer, tags);
  69. }
  70. int yaffs_mark_bad(struct yaffs_dev *dev, int block_no)
  71. {
  72. block_no -= dev->block_offset;
  73. if (dev->param.bad_block_fn)
  74. return dev->param.bad_block_fn(dev, block_no);
  75. else
  76. return yaffs_tags_compat_mark_bad(dev, block_no);
  77. }
  78. int yaffs_query_init_block_state(struct yaffs_dev *dev,
  79. int block_no,
  80. enum yaffs_block_state *state,
  81. u32 *seq_number)
  82. {
  83. block_no -= dev->block_offset;
  84. if (dev->param.query_block_fn)
  85. return dev->param.query_block_fn(dev, block_no, state,
  86. seq_number);
  87. else
  88. return yaffs_tags_compat_query_block(dev, block_no,
  89. state, seq_number);
  90. }
  91. #ifdef YAFFS_MVG_TEST_ERASECHEKFF
  92. static int yaffs_ScanCheckEraseClean(struct yaffs_dev *dev,
  93. int chunkInNAND, int page)
  94. {
  95. int retval = YAFFS_OK;
  96. u8 *data = yaffs_get_temp_buffer(dev, __LINE__);
  97. struct yaffs_ext_tags tags;
  98. int result;
  99. result = yaffs_rd_chunk_tags_nand(dev, chunkInNAND, data, &tags);
  100. if (tags.ecc_result > YAFFS_ECC_RESULT_NO_ERROR)
  101. retval = YAFFS_FAIL;
  102. if (!yaffs_check_ff(data, dev->data_bytes_per_chunk) || tags.chunk_used) {
  103. pr_err("Chunk %d not erased", chunkInNAND);
  104. retval = YAFFS_FAIL;
  105. /*add debug by jinling.ke*/
  106. pr_err("yaffsdebug Scan CheckChunk chunk:%d addr:0x%x chunkUsed:%d page:%d\n",
  107. chunkInNAND, chunkInNAND * dev->data_bytes_per_chunk, tags.chunk_used, page);
  108. mtk_dump_byte(&tags, sizeof(struct yaffs_ext_tags), 0);
  109. }
  110. yaffs_release_temp_buffer(dev, data, __LINE__);
  111. return retval;
  112. }
  113. #endif
  114. int yaffs_erase_block(struct yaffs_dev *dev, int flash_block)
  115. {
  116. int result;
  117. flash_block -= dev->block_offset;
  118. dev->n_erasures++;
  119. result = dev->param.erase_fn(dev, flash_block);
  120. #ifdef YAFFS_MVG_TEST_ERASECHEKFF
  121. for (c = 0; c < dev->param.chunks_per_block; c++)
  122. yaffs_ScanCheckEraseClean(dev, (flash_block + dev->block_offset) * dev->param.chunks_per_block + c, c);
  123. #endif
  124. return result;
  125. }
  126. #if 0
  127. int yaffs_erase_block(struct yaffs_dev *dev, int flash_block)
  128. {
  129. int result;
  130. flash_block -= dev->block_offset;
  131. dev->n_erasures++;
  132. result = dev->param.erase_fn(dev, flash_block);
  133. return result;
  134. }
  135. #endif
  136. int yaffs_init_nand(struct yaffs_dev *dev)
  137. {
  138. if (dev->param.initialise_flash_fn)
  139. return dev->param.initialise_flash_fn(dev);
  140. return YAFFS_OK;
  141. }