#include "yaffs_k9f2g08.h" #include "k9f2g08_api.h" #include "yaffs_packedtags2.h" #include "yaffs_trace.h" int ynf_init(struct yaffs_dev *dev) { yaffs_trace(YAFFS_TRACE_MTD, "ynf_init on %s", dev->param.name); return YAFFS_OK; } int ynf_write_chunk_tags(struct yaffs_dev *dev, int nand_chunk, const u8 *data, const struct yaffs_ext_tags *tags) { struct yaffs_packed_tags2 pt; void *spare; unsigned spareSize = 0; yaffs_trace(YAFFS_TRACE_MTD, "ynf_write_chunk_tags chunk %d data %p tags %p", nand_chunk, data, tags); /* For yaffs2 writing there must be both data and tags. * If we're using inband tags, then the tags are stuffed into * the end of the data buffer. */ if(dev->param.inband_tags){ struct yaffs_packed_tags2_tags_only *pt2tp; pt2tp = (struct yaffs_packed_tags2_tags_only *) (data + dev->data_bytes_per_chunk); yaffs_pack_tags2_tags_only(pt2tp,tags); spare = NULL; spareSize = 0; } else{ yaffs_pack_tags2(&pt, tags,!dev->param.no_tags_ecc); spare = &pt; spareSize = sizeof(struct yaffs_packed_tags2); } return k9f2g08_write(nand_chunk, data, spare, spareSize); } int ynf_read_chunk_tags(struct yaffs_dev *dev, int nand_chunk, u8 *data, struct yaffs_ext_tags *tags) { struct yaffs_packed_tags2 pt; int localData = 0; void *spare = NULL; unsigned spareSize; int retval = 0; int eccStatus; //0 = ok, 1 = fixed, -1 = unfixed yaffs_trace(YAFFS_TRACE_MTD, "ynf_read_chunk_tags chunk %d data %p tags %p", nand_chunk, data, tags); if(!tags){ spare = NULL; spareSize = 0; }else if(dev->param.inband_tags){ if(!data) { localData = 1; data = yaffs_get_temp_buffer(dev); } spare = NULL; spareSize = 0; } else { spare = &pt; spareSize = sizeof(struct yaffs_packed_tags2); } retval = k9f2g08_read(nand_chunk, data, spare, spareSize, &eccStatus); if(dev->param.inband_tags){ if(tags){ struct yaffs_packed_tags2_tags_only * pt2tp; pt2tp = (struct yaffs_packed_tags2_tags_only *)&data[dev->data_bytes_per_chunk]; yaffs_unpack_tags2_tags_only(tags,pt2tp); } } else { if (tags){ yaffs_unpack_tags2(tags, &pt,!dev->param.no_tags_ecc); } } if(tags && tags->chunk_used){ if(eccStatus < 0 || tags->ecc_result == YAFFS_ECC_RESULT_UNFIXED) tags->ecc_result = YAFFS_ECC_RESULT_UNFIXED; else if(eccStatus > 0 || tags->ecc_result == YAFFS_ECC_RESULT_FIXED) tags->ecc_result = YAFFS_ECC_RESULT_FIXED; else tags->ecc_result = YAFFS_ECC_RESULT_NO_ERROR; } if(localData) yaffs_release_temp_buffer(dev, data); return retval; } int ynf_mark_block_bad(struct yaffs_dev *dev, int blockId) { yaffs_trace(YAFFS_TRACE_MTD, "ynf_mark_block_bad block@%d ", blockId); return k9f2g08_mark_block_bad(blockId); } int ynf_erase_block(struct yaffs_dev *dev, int blockId) { yaffs_trace(YAFFS_TRACE_MTD, "ynf_erase_block block@%d ", blockId); return k9f2g08_erase_block(blockId); } int ynf_query_block(struct yaffs_dev *dev, int blockId, enum yaffs_block_state *state, u32 *seq_number) { unsigned chunkNo; struct yaffs_ext_tags tags; yaffs_trace(YAFFS_TRACE_MTD, "ynf_query_block block@%d ", blockId); *seq_number = 0; chunkNo = blockId * dev->param.chunks_per_block; if (!k9f2g08_is_block_ok(blockId)) { *state = YAFFS_BLOCK_STATE_DEAD; return YAFFS_OK; } ynf_read_chunk_tags(dev, chunkNo, NULL, &tags); if(!tags.chunk_used) { *state = YAFFS_BLOCK_STATE_EMPTY; } else { *state = YAFFS_BLOCK_STATE_NEEDS_SCAN; *seq_number = tags.seq_number; } return YAFFS_OK; }