1/* 2 * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. 3 * 4 * Copyright (C) 2002-2011 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#include "yaffs_nand.h" 15#include "yaffs_tagscompat.h" 16 17#include "yaffs_getblockinfo.h" 18#include "yaffs_summary.h" 19 20static int apply_chunk_offset(struct yaffs_dev *dev, int chunk) 21{ 22 return chunk - dev->chunk_offset; 23} 24 25int yaffs_rd_chunk_tags_nand(struct yaffs_dev *dev, int nand_chunk, 26 u8 *buffer, struct yaffs_ext_tags *tags) 27{ 28 int result; 29 struct yaffs_ext_tags local_tags; 30 int flash_chunk = apply_chunk_offset(dev, nand_chunk); 31 32 dev->n_page_reads++; 33 34 /* If there are no tags provided use local tags. */ 35 if (!tags) 36 tags = &local_tags; 37 38 result = dev->tagger.read_chunk_tags_fn(dev, flash_chunk, buffer, tags); 39 if (tags && tags->ecc_result > YAFFS_ECC_RESULT_NO_ERROR) { 40 41 struct yaffs_block_info *bi; 42 bi = yaffs_get_block_info(dev, 43 nand_chunk / 44 dev->param.chunks_per_block); 45 yaffs_handle_chunk_error(dev, bi); 46 } 47 return result; 48} 49 50int yaffs_wr_chunk_tags_nand(struct yaffs_dev *dev, 51 int nand_chunk, 52 const u8 *buffer, struct yaffs_ext_tags *tags) 53{ 54 int result; 55 int flash_chunk = apply_chunk_offset(dev, nand_chunk); 56 57 dev->n_page_writes++; 58 59 if (!tags) { 60 yaffs_trace(YAFFS_TRACE_ERROR, "Writing with no tags"); 61 BUG(); 62 return YAFFS_FAIL; 63 } 64 65 tags->seq_number = dev->seq_number; 66 tags->chunk_used = 1; 67 yaffs_trace(YAFFS_TRACE_WRITE, 68 "Writing chunk %d tags %d %d", 69 nand_chunk, tags->obj_id, tags->chunk_id); 70 71 result = dev->tagger.write_chunk_tags_fn(dev, flash_chunk, 72 buffer, tags); 73 74 yaffs_summary_add(dev, tags, nand_chunk); 75 76 return result; 77} 78 79int yaffs_mark_bad(struct yaffs_dev *dev, int block_no) 80{ 81 block_no -= dev->block_offset; 82 dev->n_bad_markings++; 83 84 if (dev->param.disable_bad_block_marking) 85 return YAFFS_OK; 86 87 return dev->tagger.mark_bad_fn(dev, block_no); 88} 89 90 91int yaffs_query_init_block_state(struct yaffs_dev *dev, 92 int block_no, 93 enum yaffs_block_state *state, 94 u32 *seq_number) 95{ 96 block_no -= dev->block_offset; 97 return dev->tagger.query_block_fn(dev, block_no, state, seq_number); 98} 99 100int yaffs_erase_block(struct yaffs_dev *dev, int block_no) 101{ 102 int result; 103 104 block_no -= dev->block_offset; 105 dev->n_erasures++; 106 result = dev->drv.drv_erase_fn(dev, block_no); 107 return result; 108} 109 110int yaffs_init_nand(struct yaffs_dev *dev) 111{ 112 if (dev->drv.drv_initialise_fn) 113 return dev->drv.drv_initialise_fn(dev); 114 return YAFFS_OK; 115} 116 117int yaffs_deinit_nand(struct yaffs_dev *dev) 118{ 119 if (dev->drv.drv_deinitialise_fn) 120 return dev->drv.drv_deinitialise_fn(dev); 121 return YAFFS_OK; 122} 123