From: Charles Manning Date: Tue, 2 Oct 2012 02:41:32 +0000 (+1300) Subject: Merge branch 'driver-refactoring' into new-driver-refactoring X-Git-Tag: aleph1-release~73 X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=commitdiff_plain;h=54721f22512e7c859c4c4a4ae7e5374ecf7fb570;hp=d634851c1f36e7995726602d3af784478ccb472e Merge branch 'driver-refactoring' into new-driver-refactoring --- diff --git a/Makefile b/Makefile index 6722182..a346458 100644 --- a/Makefile +++ b/Makefile @@ -27,11 +27,12 @@ ifneq ($(KERNELRELEASE),) obj-m := $(YAFFS_O) - yaffs2-objs := yaffs_mtdif.o yaffs_mtdif2_single.o - yaffs2-objs += yaffs_mtdif1_single.o yaffs_packedtags1.o + yaffs2-objs := yaffs_mtdif_single.o + yaffs2-objs += yaffs_packedtags1.o yaffs2-objs += yaffs_ecc.o yaffs_vfs_single.o yaffs_guts.o yaffs2-objs += yaffs_packedtags2.o yaffs2-objs += yaffs_tagscompat.o + yaffs2-objs += yaffs_tagsmarshall.o yaffs2-objs += yaffs_checkptrw.o yaffs_nand.o yaffs2-objs += yaffs_checkptrw.o yaffs_nand.o yaffs_nameval.o yaffs2-objs += yaffs_allocator.o yaffs_bitmap.o yaffs_attribs.o @@ -40,11 +41,12 @@ ifneq ($(KERNELRELEASE),) yaffs2-objs += yaffs_verify.o yaffs2-objs += yaffs_summary.o - yaffs2multi-objs := yaffs_mtdif.o yaffs_mtdif2_multi.o - yaffs2multi-objs += yaffs_mtdif1_multi.o yaffs_packedtags1.o + yaffs2multi-objs := yaffs_mtdif_multi.o + yaffs2multi-objs += yaffs_packedtags1.o yaffs2multi-objs += yaffs_ecc.o yaffs_vfs_multi.o yaffs_guts.o yaffs2multi-objs += yaffs_packedtags2.o yaffs2multi-objs += yaffs_tagscompat.o + yaffs2multi-objs += yaffs_tagsmarshall.o yaffs2multi-objs += yaffs_checkptrw.o yaffs_nand.o yaffs2multi-objs += yaffs_checkptrw.o yaffs_nand.o yaffs_nameval.o yaffs2multi-objs += yaffs_allocator.o yaffs_bitmap.o yaffs_attribs.o diff --git a/direct/basic-test/Makefile b/direct/basic-test/Makefile deleted file mode 100644 index 026c0b8..0000000 --- a/direct/basic-test/Makefile +++ /dev/null @@ -1,107 +0,0 @@ -# Makefile for YAFFS direct test -# -# -# YAFFS: Yet another Flash File System. A NAND-flash specific file system. -# -# Copyright (C) 2003-2010 Aleph One Ltd. -# -# -# Created by Charles Manning -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2 as -# published by the Free Software Foundation. -# -# NB Warning this Makefile does not include header dependencies. -# -# $Id: Makefile,v 1.24 2010-02-17 02:18:57 charles Exp $ - -#EXTRA_COMPILE_FLAGS = -DYAFFS_IGNORE_TAGS_ECC - -CFLAGS = -DCONFIG_YAFFS_DIRECT -DCONFIG_YAFFS_YAFFS2 -D CONFIG_YAFFS_DEFINES_TYPES -CFLAGS += -DCONFIG_YAFFS_PROVIDE_DEFS -DCONFIG_YAFFSFS_PROVIDE_VALUES -DNO_Y_INLINE -CFLAGS += -Wall -g $(EXTRA_COMPILE_FLAGS) -Werror=strict-aliasing -#CFLAGS += -fno-strict-aliasing -CFLAGS += -O0 -#CFLAGS += -DVALGRIND_TEST -#CFLAGS += -DCONFIG_YAFFS_CASE_INSENSITIVE - -CFLAGS+= -Wshadow -Werror=pointer-arith -Werror=write-strings -CFLAGS+= -Werror=strict-prototypes -Werror=missing-parameter-type -CFLAGS+= -Werror=redundant-decls -Werror=nested-externs -Winline -CFLAGS+= -Werror=undef - -CFLAGS+= -DCONFIG_YAFFS_USE_PTHREADS -lpthread - - -COMMONTESTOBJS = yaffscfg2k.o yaffs_osglue.o yaffs_hweight.o \ - yaffs_ecc.o yaffs_fileem.o yaffs_fileem2k.o yaffsfs.o yaffs_guts.o \ - yaffs_packedtags1.o yaffs_ramdisk.o yaffs_ramem2k.o \ - yaffs_tagscompat.o yaffs_packedtags2.o yaffs_nand.o \ - yaffs_checkptrw.o yaffs_qsort.o\ - yaffs_nameval.o yaffs_attribs.o \ - yaffs_norif1.o ynorsim.o \ - yaffs_allocator.o \ - yaffs_bitmap.o \ - yaffs_yaffs1.o \ - yaffs_yaffs2.o \ - yaffs_verify.o \ - yaffs_summary.o - -# yaffs_checkptrwtest.o\ - - -YAFFSDIRECTSYMLINKS = \ - yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h \ - yaffs_tagscompat.c yaffs_tagscompat.h \ - yaffs_packedtags1.c yaffs_packedtags1.h yaffs_packedtags2.c yaffs_packedtags2.h \ - yaffs_nand.c yaffs_nand.h yaffs_getblockinfo.h \ - yaffs_checkptrw.h yaffs_checkptrw.c \ - yaffs_nameval.c yaffs_nameval.h \ - yaffs_trace.h yaffs_attribs.h \ - yaffs_allocator.c yaffs_allocator.h \ - yaffs_yaffs1.c yaffs_yaffs1.h \ - yaffs_yaffs2.c yaffs_yaffs2.h \ - yaffs_bitmap.c yaffs_bitmap.h \ - yaffs_verify.c yaffs_verify.h \ - yaffs_summary.c yaffs_summary.h \ - yaffsfs.c yaffs_flashif.h yaffs_flashif2.h\ - yaffsfs.h yaffs_osglue.h ydirectenv.h \ - yaffscfg.h yaffs_list.h \ - yaffs_qsort.c yportenv.h yaffs_attribs.c \ - yaffs_nandif.c yaffs_nandif.h yaffs_nandemul2k.h \ - yaffs_hweight.h yaffs_hweight.c \ - - - -DIRECTTESTOBJS = $(COMMONTESTOBJS) dtest.o - -BOOTTESTOBJS = bootldtst.o yboot.o yaffs_fileem.o nand_ecc.o - -ALLOBJS = $(sort $(DIRECTTESTOBJS) $(YAFFSTESTOBJS)) - -TARGETS = directtest2k - -all: $(TARGETS) - -$(ALLOBJS): %.o: %.c - gcc -c $(CFLAGS) -o $@ $< - - -$(YAFFSDIRECTSYMLINKS): - ln -s ../$@ $@ - - -directtest2k: $(YAFFSDIRECTSYMLINKS) $(DIRECTTESTOBJS) - gcc -o $@ $(DIRECTTESTOBJS) - -yaffs_test: $(YAFFSDIRECTSYMLINKS) $(YAFFSTESTOBJS) - gcc -o $@ $(YAFFSTESTOBJS) - - -boottest: $(YAFFSDIRECTSYMLINKS) $(BOOTTESTOBJS) - gcc -o $@ $(BOOTTESTOBJS) - - -clean: - rm -f $(TARGETS) $(ALLOBJS) core $(YAFFSDIRECTSYMLINKS) diff --git a/direct/basic-test/yaffs_fileem2k.c b/direct/basic-test/yaffs_fileem2k.c deleted file mode 100644 index 836d1f7..0000000 --- a/direct/basic-test/yaffs_fileem2k.c +++ /dev/null @@ -1,602 +0,0 @@ -/* - * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. - * - * Copyright (C) 2002-2011 Aleph One Ltd. - * for Toby Churchill Ltd and Brightstar Engineering - * - * Created by Charles Manning - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -/* - * This provides a YAFFS nand emulation on a file for emulating 2kB pages. - * This is only intended as test code to test persistence etc. - */ - -const char *yaffs_flashif2_c_version = "$Id: yaffs_fileem2k.c,v 1.24 2010-02-18 01:18:04 charles Exp $"; - - -#include "yportenv.h" -#include "yaffs_trace.h" - -#include "yaffs_flashif2.h" -#include "yaffs_guts.h" -#include "yaffs_fileem2k.h" -#include "yaffs_packedtags2.h" - - -#include -#include -#include -#include - - - -#define REPORT_ERROR 0 - -typedef struct -{ - u8 data[PAGE_SIZE]; // Data + spare -} yflash_Page; - -typedef struct -{ - yflash_Page page[PAGES_PER_BLOCK]; // The pages in the block - -} yflash_Block; - - - -#define MAX_HANDLES 20 -#define BLOCKS_PER_HANDLE (32*8) - -typedef struct -{ - int handle[MAX_HANDLES]; - int nBlocks; -} yflash_Device; - -static yflash_Device filedisk; - -int yaffs_test_partial_write = 0; - -extern int random_seed; -extern int simulate_power_failure; -static int remaining_ops; -static int nops_so_far; - -int ops_multiplier; - - -static void yflash2_MaybePowerFail(unsigned int nand_chunk, int failPoint) -{ - - nops_so_far++; - - - remaining_ops--; - if(simulate_power_failure && - remaining_ops < 1){ - printf("Simulated power failure after %d operations\n",nops_so_far); - printf(" power failed on nand_chunk %d, at fail point %d\n", - nand_chunk, failPoint); - exit(0); - } -} - - - - - -static u8 localBuffer[PAGE_SIZE]; - -static char *NToName(char *buf,int n) -{ - sprintf(buf,"emfile-2k-%d",n); - return buf; -} - -static char dummyBuffer[BLOCK_SIZE]; - -static int GetBlockFileHandle(int n) -{ - int h; - int requiredSize; - - char name[40]; - NToName(name,n); - int fSize; - int i; - - h = open(name, O_RDWR | O_CREAT, S_IREAD | S_IWRITE); - if(h >= 0){ - fSize = lseek(h,0,SEEK_END); - requiredSize = BLOCKS_PER_HANDLE * BLOCK_SIZE; - if(fSize < requiredSize){ - for(i = 0; i < BLOCKS_PER_HANDLE; i++) - if(write(h,dummyBuffer,BLOCK_SIZE) != BLOCK_SIZE) - return -1; - - } - } - - return h; - -} - -static int CheckInit(void) -{ - static int initialised = 0; - int i; - - int blk; - - - if(initialised) - { - return YAFFS_OK; - } - - initialised = 1; - - - srand(random_seed); - remaining_ops = (rand() % 1000) * 5; - memset(dummyBuffer,0xff,sizeof(dummyBuffer)); - - - - filedisk.nBlocks = SIZE_IN_MB * BLOCKS_PER_MB; - - for(i = 0; i < MAX_HANDLES; i++) - filedisk.handle[i] = -1; - - for(i = 0,blk = 0; blk < filedisk.nBlocks; blk+=BLOCKS_PER_HANDLE,i++) - filedisk.handle[i] = GetBlockFileHandle(i); - - - return 1; -} - - -int yflash2_GetNumberOfBlocks(void) -{ - CheckInit(); - - return filedisk.nBlocks; -} - -int yflash2_WriteChunkWithTagsToNAND(struct yaffs_dev *dev,int nand_chunk,const u8 *data, const struct yaffs_ext_tags *tags) -{ - int written; - int pos; - int h; - int i; - int nRead; - int error; - - yaffs_trace(YAFFS_TRACE_MTD, "write chunk %d data %p tags %p",nand_chunk, data, tags); - - CheckInit(); - - - 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); - - pos = (nand_chunk % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE; - h = filedisk.handle[(nand_chunk / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))]; - - lseek(h,pos,SEEK_SET); - written = write(h,data,dev->param.total_bytes_per_chunk); - - - if(yaffs_test_partial_write){ - close(h); - exit(1); - } - - if(written != dev->param.total_bytes_per_chunk) return YAFFS_FAIL; - - - } - - else { - /* First do a write of a partial page */ - int n_partials; - int bpos; - - if(data) - { - pos = (nand_chunk % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE; - h = filedisk.handle[(nand_chunk / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))]; - - - memcpy(localBuffer,data, dev->data_bytes_per_chunk); - - n_partials = rand()%20; - - for(i = 0; i < n_partials; i++){ - bpos = rand() % dev->data_bytes_per_chunk; - - localBuffer[bpos] |= (1 << (rand() & 7)); - } - - if(REPORT_ERROR && memcmp(localBuffer,data,dev->data_bytes_per_chunk)) - printf("nand simulator: data does not match\n"); - - lseek(h,pos,SEEK_SET); - written = write(h,localBuffer,dev->data_bytes_per_chunk); - - if(yaffs_test_partial_write){ - close(h); - exit(1); - } - - - if(written != dev->data_bytes_per_chunk) return YAFFS_FAIL; - } - // yflash2_MaybePowerFail(nand_chunk,1); - - if(tags) - { - pos = (nand_chunk % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE + PAGE_DATA_SIZE ; - h = filedisk.handle[(nand_chunk / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))]; - - lseek(h,pos,SEEK_SET); - - if( 0 && dev->param.is_yaffs2) - { - - written = write(h,tags,sizeof(struct yaffs_ext_tags)); - if(written != sizeof(struct yaffs_ext_tags)) return YAFFS_FAIL; - } - else - { - struct yaffs_packed_tags2 pt; - yaffs_pack_tags2(&pt,tags, !dev->param.no_tags_ecc); - u8 * ptab = (u8 *)&pt; - - nRead = read(h,localBuffer,sizeof(pt)); - for(i = error = 0; REPORT_ERROR && i < sizeof(pt) && !error; i++){ - if(localBuffer[i] != 0xFF){ - printf("nand simulation: chunk %d oob byte %d was %0x2\n", - nand_chunk,i,localBuffer[i]); - error = 1; - } - } - - for(i = 0; i < sizeof(pt); i++) - localBuffer[i] &= ptab[i]; - - n_partials = rand()% sizeof(pt); - - for(i = 0; i < n_partials; i++){ - bpos = rand() % sizeof(pt); - - localBuffer[bpos] |= (1 << (rand() & 7)); - } - - if(REPORT_ERROR && memcmp(localBuffer,&pt,sizeof(pt))) - printf("nand sim: tags corruption\n"); - - lseek(h,pos,SEEK_SET); - - written = write(h,localBuffer,sizeof(pt)); - if(written != sizeof(pt)) return YAFFS_FAIL; - } - } - - //yflash2_MaybePowerFail(nand_chunk,2); - - /* Next do the whole write */ - if(data) - { - pos = (nand_chunk % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE; - h = filedisk.handle[(nand_chunk / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))]; - - - memset(localBuffer,0xFF, PAGE_SIZE); - for(i = 0; i < dev->data_bytes_per_chunk; i++){ - localBuffer[i] &= data[i]; - } - - if(REPORT_ERROR && memcmp(localBuffer,data,dev->data_bytes_per_chunk)) - printf("nand simulator: data does not match\n"); - - lseek(h,pos,SEEK_SET); - written = write(h,localBuffer,dev->data_bytes_per_chunk); - - if(yaffs_test_partial_write){ - close(h); - exit(1); - } - - - if(written != dev->data_bytes_per_chunk) return YAFFS_FAIL; - } - - if(tags) - { - pos = (nand_chunk % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE + PAGE_DATA_SIZE ; - h = filedisk.handle[(nand_chunk / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))]; - - lseek(h,pos,SEEK_SET); - - if( 0 && dev->param.is_yaffs2) - { - - written = write(h,tags,sizeof(struct yaffs_ext_tags)); - if(written != sizeof(struct yaffs_ext_tags)) return YAFFS_FAIL; - } - else - { - struct yaffs_packed_tags2 pt; - yaffs_pack_tags2(&pt,tags,!dev->param.no_tags_ecc); - u8 * ptab = (u8 *)&pt; - - nRead = read(h,localBuffer,sizeof(pt)); - for(i = error = 0; REPORT_ERROR && i < sizeof(pt) && !error; i++){ - if(localBuffer[i] != 0xFF){ - printf("nand simulation: chunk %d oob byte %d was %0x2\n", - nand_chunk,i,localBuffer[i]); - error = 1; - } - } - - for(i = 0; i < sizeof(pt); i++) - localBuffer[i] &= ptab[i]; - - if(REPORT_ERROR && memcmp(localBuffer,&pt,sizeof(pt))) - printf("nand sim: tags corruption\n"); - - lseek(h,pos,SEEK_SET); - - written = write(h,localBuffer,sizeof(pt)); - if(written != sizeof(pt)) return YAFFS_FAIL; - } - } - - yflash2_MaybePowerFail(nand_chunk,3); - - } - return YAFFS_OK; - -} - -int yaffs_check_all_ff(const u8 *ptr, int n) -{ - while(n) - { - n--; - if(*ptr!=0xFF) return 0; - ptr++; - } - return 1; -} - - -static int fail300 = 1; -static int fail320 = 1; - -static int failRead10 = 2; - -int yflash2_ReadChunkWithTagsFromNAND(struct yaffs_dev *dev,int nand_chunk, u8 *data, struct yaffs_ext_tags *tags) -{ - int nread; - int pos; - int h; - int localData = 0; - int retval = YAFFS_OK; - int nRead; - - yaffs_trace(YAFFS_TRACE_MTD,"read chunk %d data %p tags %p",nand_chunk, data, tags); - - CheckInit(); - - - - - if(dev->param.inband_tags){ - /* Got to suck the tags out of the data area */ - if(!data) { - localData=1; - data = yaffs_get_temp_buffer(dev); - } - - - struct yaffs_packed_tags2_tags_only * pt2tp; - pt2tp = (struct yaffs_packed_tags2_tags_only *)&data[dev->data_bytes_per_chunk]; - - - pos = (nand_chunk % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE; - h = filedisk.handle[(nand_chunk / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))]; - - lseek(h,pos,SEEK_SET); - - nRead = read(h, data,dev->param.total_bytes_per_chunk); - - yaffs_unpack_tags2_tags_only(tags,pt2tp); - - if(nread != dev->param.total_bytes_per_chunk) - retval = YAFFS_FAIL; - - if(localData) - yaffs_release_temp_buffer(dev, data); - - - - } - - else { - - if(data) - { - - pos = (nand_chunk % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE; - h = filedisk.handle[(nand_chunk / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))]; - lseek(h,pos,SEEK_SET); - nread = read(h,data,dev->data_bytes_per_chunk); - - - if(nread != dev->data_bytes_per_chunk) - retval = YAFFS_FAIL; - } - - if(tags) - { - pos = (nand_chunk % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE + PAGE_DATA_SIZE; - h = filedisk.handle[(nand_chunk / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))]; - lseek(h,pos,SEEK_SET); - - if(0 && dev->param.is_yaffs2) - { - nread= read(h,tags,sizeof(struct yaffs_ext_tags)); - if(nread != sizeof(struct yaffs_ext_tags)) - retval = YAFFS_FAIL; - if(yaffs_check_all_ff((u8 *)tags, sizeof(struct yaffs_ext_tags))) - memset(tags, 0, sizeof(struct yaffs_ext_tags)); - else - tags->chunk_used = 1; - } - else - { - struct yaffs_packed_tags2 pt; - nread= read(h,&pt,sizeof(pt)); - yaffs_unpack_tags2(tags,&pt, !dev->param.no_tags_ecc); -#ifdef SIMULATE_FAILURES - if((nand_chunk >> 6) == 100) { - if(fail300 && tags->ecc_result == YAFFS_ECC_RESULT_NO_ERROR){ - tags->ecc_result = YAFFS_ECC_RESULT_FIXED; - fail300 = 0; - } - } - - if((nand_chunk >> 6) == 110) { - if(fail320 && tags->ecc_result == YAFFS_ECC_RESULT_NO_ERROR){ - tags->ecc_result = YAFFS_ECC_RESULT_FIXED; - fail320 = 0; - } - } -#endif - if(failRead10>0 && nand_chunk == 10){ - failRead10--; - nread = 0; - } - - if(nread != sizeof(pt)) - retval = YAFFS_FAIL; - } - } - } - - - - return retval; - -} - - -int yflash2_MarkNANDBlockBad(struct yaffs_dev *dev, int block_no) -{ - int written; - int h; - - struct yaffs_packed_tags2 pt; - - CheckInit(); - - memset(&pt,0,sizeof(pt)); - h = filedisk.handle[(block_no / ( BLOCKS_PER_HANDLE))]; - lseek(h,((block_no % BLOCKS_PER_HANDLE) * dev->param.chunks_per_block) * PAGE_SIZE + PAGE_DATA_SIZE,SEEK_SET); - written = write(h,&pt,sizeof(pt)); - - if(written != sizeof(pt)) return YAFFS_FAIL; - - - return YAFFS_OK; - -} - -int yflash2_EraseBlockInNAND(struct yaffs_dev *dev, int blockNumber) -{ - - int i; - int h; - - CheckInit(); - - //printf("erase block %d\n",blockNumber); - - if(blockNumber == 320) - fail320 = 1; - - if(blockNumber < 0 || blockNumber >= filedisk.nBlocks) - { - yaffs_trace(YAFFS_TRACE_ALWAYS,"Attempt to erase non-existant block %d",blockNumber); - return YAFFS_FAIL; - } - else - { - - u8 pg[PAGE_SIZE]; - int syz = PAGE_SIZE; - int pos; - - memset(pg,0xff,syz); - - - h = filedisk.handle[(blockNumber / ( BLOCKS_PER_HANDLE))]; - lseek(h,((blockNumber % BLOCKS_PER_HANDLE) * dev->param.chunks_per_block) * PAGE_SIZE,SEEK_SET); - for(i = 0; i < dev->param.chunks_per_block; i++) - { - write(h,pg,PAGE_SIZE); - } - pos = lseek(h, 0,SEEK_CUR); - - return YAFFS_OK; - } - -} - -int yflash2_InitialiseNAND(struct yaffs_dev *dev) -{ - CheckInit(); - - return YAFFS_OK; -} - - - - -int yflash2_QueryNANDBlock(struct yaffs_dev *dev, int block_no, enum yaffs_block_state *state, u32 *seq_number) -{ - struct yaffs_ext_tags tags; - int chunkNo; - - *seq_number = 0; - - chunkNo = block_no * dev->param.chunks_per_block; - - yflash2_ReadChunkWithTagsFromNAND(dev,chunkNo,NULL,&tags); - if(tags.block_bad) - { - *state = YAFFS_BLOCK_STATE_DEAD; - } - else if(!tags.chunk_used) - { - *state = YAFFS_BLOCK_STATE_EMPTY; - } - else if(tags.chunk_used) - { - *state = YAFFS_BLOCK_STATE_NEEDS_SCAN; - *seq_number = tags.seq_number; - } - return YAFFS_OK; -} - diff --git a/direct/basic-test/yaffs_fileem2k.h b/direct/basic-test/yaffs_fileem2k.h deleted file mode 100644 index e2e8dc3..0000000 --- a/direct/basic-test/yaffs_fileem2k.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * YAFFS: Yet another Flash File System . A NAND-flash specific file system. - * - * Copyright (C) 2002-2011 Aleph One Ltd. - * for Toby Churchill Ltd and Brightstar Engineering - * - * Created by Charles Manning - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 as - * published by the Free Software Foundation. - * - * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. - */ - -#ifndef __FILEEM2K_H__ -#define __FILEEM2K_H__ - -#if 1 - -#define SIZE_IN_MB 32 -/* #define SIZE_IN_MB 128 */ - -#define PAGE_DATA_SIZE (2048) -#define PAGE_SPARE_SIZE (64) -#define PAGE_SIZE (PAGE_DATA_SIZE + PAGE_SPARE_SIZE) -#define PAGES_PER_BLOCK (64) -#define BLOCK_DATA_SIZE (PAGE_DATA_SIZE * PAGES_PER_BLOCK) -#define BLOCK_SIZE (PAGES_PER_BLOCK * (PAGE_SIZE)) -#define BLOCKS_PER_MB ((1024*1024)/BLOCK_DATA_SIZE) -#define SIZE_IN_BLOCKS (BLOCKS_PER_MB * SIZE_IN_MB) - -#else - -#define SIZE_IN_MB 128 -#define PAGE_DATA_SIZE (512) -#define SPARE_SIZE (16) -#define PAGE_SIZE (PAGE_DATA_SIZE + SPARE_SIZE) -#define PAGES_PER_BLOCK (32) -#define BLOCK_DATA_SIZE (PAGE_SIZE * PAGES_PER_BLOCK) -#define BLOCK_SIZE (PAGES_PER_BLOCK * (PAGE_SIZE)) -#define BLOCKS_PER_MB ((1024*1024)/BLOCK_DATA_SIZE) -#define SIZE_IN_BLOCKS (BLOCKS_PER_MB * SIZE_IN_MB) - -#endif - - -int yflash2_GetNumberOfBlocks(void); - -#endif - diff --git a/direct/basic-test/yaffscfg2k.c b/direct/basic-test/yaffscfg2k.c deleted file mode 100644 index bbaacb9..0000000 --- a/direct/basic-test/yaffscfg2k.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. - * - * Copyright (C) 2002-2011 Aleph One Ltd. - * for Toby Churchill Ltd and Brightstar Engineering - * - * Created by Charles Manning - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -/* - * yaffscfg2k.c The configuration for the "direct" use of yaffs. - * - * This file is intended to be modified to your requirements. - * There is no need to redistribute this file. - */ - -#include "yaffscfg.h" -#include "yaffs_guts.h" -#include "yaffsfs.h" -#include "yaffs_fileem2k.h" -#include "yaffs_nandemul2k.h" -#include "yaffs_norif1.h" -#include "yaffs_trace.h" -#include "yaffs_osglue.h" - - -#include - -unsigned yaffs_trace_mask = - - YAFFS_TRACE_SCAN | - YAFFS_TRACE_GC | - YAFFS_TRACE_ERASE | - YAFFS_TRACE_ERROR | - YAFFS_TRACE_TRACING | - YAFFS_TRACE_ALLOCATE | - YAFFS_TRACE_BAD_BLOCKS | - YAFFS_TRACE_VERIFY | - - 0; - - - -// Configuration - -#include "yaffs_ramdisk.h" -#include "yaffs_flashif.h" -#include "yaffs_flashif2.h" -#include "yaffs_nandemul2k.h" - -struct yaffs_dev ram1Dev; -struct yaffs_dev flashDev; -struct yaffs_dev m18_1Dev; - -int yaffs_start_up(void) -{ - static int start_up_called = 0; - - if(start_up_called) - return; - start_up_called = 1; - - // Stuff to configure YAFFS - // Stuff to initialise anything special (eg lock semaphore). - yaffsfs_OSInitialisation(); - - // Set up devices - // /ram1 ram, yaffs1 - memset(&ram1Dev,0,sizeof(ram1Dev)); - ram1Dev.param.name = "ram1"; - ram1Dev.param.total_bytes_per_chunk = 512; - ram1Dev.param.chunks_per_block = 32; - ram1Dev.param.n_reserved_blocks = 2; // Set this smaller for RAM - ram1Dev.param.start_block = 0; // Can use block 0 - ram1Dev.param.end_block = 127; // Last block in 2MB. - //ram1Dev.param.use_nand_ecc = 1; - ram1Dev.param.n_caches = 0; // Disable caching on this device. - ram1Dev.driver_context = (void *) 0; // Used to identify the device in fstat. - ram1Dev.param.write_chunk_tags_fn = yramdisk_wr_chunk; - ram1Dev.param.read_chunk_tags_fn = yramdisk_rd_chunk; - ram1Dev.param.erase_fn = yramdisk_erase; - ram1Dev.param.initialise_flash_fn = yramdisk_initialise; - - yaffs_add_device(&ram1Dev); - - // /M18-1 yaffs1 on M18 nor sim - memset(&m18_1Dev,0,sizeof(m18_1Dev)); - m18_1Dev.param.name = "M18-1"; - m18_1Dev.param.total_bytes_per_chunk = 1024; - m18_1Dev.param.chunks_per_block =248; - m18_1Dev.param.n_reserved_blocks = 2; - m18_1Dev.param.start_block = 0; // Can use block 0 - m18_1Dev.param.end_block = 31; // Last block - m18_1Dev.param.use_nand_ecc = 0; // use YAFFS's ECC - m18_1Dev.param.n_caches = 10; // Use caches - m18_1Dev.param.disable_soft_del = 1; - m18_1Dev.driver_context = (void *) 1; // Used to identify the device in fstat. - m18_1Dev.param.write_chunk_fn = ynorif1_WriteChunkToNAND; - m18_1Dev.param.read_chunk_fn = ynorif1_ReadChunkFromNAND; - m18_1Dev.param.erase_fn = ynorif1_EraseBlockInNAND; - m18_1Dev.param.initialise_flash_fn = ynorif1_InitialiseNAND; - m18_1Dev.param.deinitialise_flash_fn = ynorif1_Deinitialise_flash_fn; - -// m18_1Dev.param.disable_soft_del = 1; - - yaffs_add_device(&m18_1Dev); - - // /yaffs2 yaffs2 file emulation - // 2kpage/64chunk per block - // - memset(&flashDev,0,sizeof(flashDev)); - flashDev.param.name = "yaffs2"; - flashDev.param.total_bytes_per_chunk = 2048; - flashDev.param.chunks_per_block = 64; - flashDev.param.n_reserved_blocks = 5; - flashDev.param.inband_tags = 0; - flashDev.param.start_block = 0; - flashDev.param.end_block = yflash2_GetNumberOfBlocks()-1; - flashDev.param.is_yaffs2 = 1; - flashDev.param.use_nand_ecc=1; - flashDev.param.wide_tnodes_disabled=0; - flashDev.param.refresh_period = 1000; - flashDev.param.n_caches = 10; // Use caches - flashDev.driver_context = (void *) 2; // Used to identify the device in fstat. - flashDev.param.write_chunk_tags_fn = yflash2_WriteChunkWithTagsToNAND; - flashDev.param.read_chunk_tags_fn = yflash2_ReadChunkWithTagsFromNAND; - flashDev.param.erase_fn = yflash2_EraseBlockInNAND; - flashDev.param.initialise_flash_fn = yflash2_InitialiseNAND; - flashDev.param.bad_block_fn = yflash2_MarkNANDBlockBad; - flashDev.param.query_block_fn = yflash2_QueryNANDBlock; - flashDev.param.enable_xattr = 1; - - yaffs_add_device(&flashDev); - -// todo yaffs_initialise(yaffsfs_config); - - return 0; -} - - - diff --git a/direct/handle_common.sh b/direct/handle_common.sh index 0e339f1..2b5a043 100755 --- a/direct/handle_common.sh +++ b/direct/handle_common.sh @@ -3,6 +3,7 @@ YAFFS_COMMON_SOURCES="\ yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h \ yaffs_tagscompat.c yaffs_tagscompat.h \ + yaffs_tagsmarshall.c yaffs_tagsmarshall.h \ yaffs_packedtags1.c yaffs_packedtags1.h \ yaffs_packedtags2.c yaffs_packedtags2.h \ yaffs_nand.c yaffs_nand.h yaffs_getblockinfo.h \ @@ -19,6 +20,7 @@ YAFFS_COMMON_SOURCES="\ if [ "$1" = "copy" ] ; then +set -e -x for i in $YAFFS_COMMON_SOURCES ; do sed ../$i \ -e "s/strcat/yaffs_strcat/g" \ diff --git a/direct/python/Makefile b/direct/python/Makefile deleted file mode 100644 index 2c70f5a..0000000 --- a/direct/python/Makefile +++ /dev/null @@ -1,104 +0,0 @@ -# Makefile for YAFFS direct stress tests -# -# -# YAFFS: Yet another Flash File System. A NAND-flash specific file system. -# -# Copyright (C) 2003-2010 Aleph One Ltd. -# -# -# Created by Charles Manning -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2 as -# published by the Free Software Foundation. -# -# NB Warning this Makefile does not include header dependencies. -# -# $Id: Makefile,v 1.6 2010-02-17 00:51:15 charles Exp $ - -#EXTRA_COMPILE_FLAGS = -DYAFFS_IGNORE_TAGS_ECC - -CFLAGS = -DCONFIG_YAFFS_DIRECT -DCONFIG_YAFFS_YAFFS2 -DCONFIG_YAFFS_DEFINES_TYPES -CFLAGS += -DCONFIG_YAFFS_PROVIDE_DEFS -DCONFIG_YAFFSFS_PROVIDE_VALUES -DNO_Y_INLINE -CFLAGS += -Wall -g $(EXTRA_COMPILE_FLAGS) -Wstrict-aliasing -#CFLAGS += -fno-strict-aliasing -CFLAGS += -O0 -fPIC -#CFLAGS += -DVALGRIND_TEST - -#CFLAGS+= -Wshadow -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Wmissing-declarations -#CFLAGS+= -Wmissing-prototypes -Wredundant-decls -Wnested-externs -Winline - - -COMMONTESTOBJS = yaffscfg2k.o yaffs_osglue.o yaffs_hweight.o\ - yramsim.o yaffs_fileem2k.o\ - yaffs_nandif.o yaffs_attribs.o \ - yaffsfs.o yaffs_ecc.o yaffs_guts.o \ - yaffs_packedtags1.o yaffs_ramdisk.o yaffs_ramem2k.o \ - yaffs_tagscompat.o yaffs_packedtags2.o yaffs_nand.o \ - yaffs_checkptrw.o yaffs_qsort.o\ - yaffs_nameval.o \ - yaffs_summary.o \ - yaffs_allocator.o \ - yaffs_norif1.o ynorsim.o \ - yaffs_bitmap.o \ - yaffs_verify.o \ - yaffs_yaffs1.o yaffs_yaffs2.o \ - yaffs_error.o - - -YAFFSLIBOBJS = $(COMMONTESTOBJS) yaffs_python_helper.o - - - - - -YAFFSDIRECTSYMLINKS = \ - yaffsfs.c yaffsfs.h yaffscfg.h yaffs_osglue.h ydirectenv.h \ - yaffs_flashif.h yaffs_flashif2.h yaffs_list.h \ - yaffs_nandif.c yaffs_nandif.h yaffs_qsort.c yaffs_nandemul2k.h \ - yportenv.h yaffs_attribs.c \ - yaffs_hweight.c yaffs_hweight.h \ - yaffs_error.c \ - yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h yaffs_tagscompat.c yaffs_tagscompat.h \ - yaffs_packedtags1.c yaffs_packedtags1.h yaffs_packedtags2.c yaffs_packedtags2.h \ - yaffs_nand.c yaffs_nand.h yaffs_getblockinfo.h \ - yaffs_checkptrw.h yaffs_checkptrw.c \ - yaffs_summary.c yaffs_summary.h \ - yaffs_nameval.c yaffs_nameval.h yaffs_attribs.h \ - yaffs_trace.h \ - yaffs_allocator.c yaffs_allocator.h \ - yaffs_yaffs1.c yaffs_yaffs1.h \ - yaffs_yaffs2.c yaffs_yaffs2.h \ - yaffs_bitmap.c yaffs_bitmap.h \ - yaffs_verify.c yaffs_verify.h - -DIRECTEXTRASYMLINKS = yaffscfg2k.c yaffs_fileem2k.c yaffs_fileem2k.h\ - yaffs_fileem.c yaffs_norif1.c yaffs_norif1.h \ - yaffs_ramdisk.c yaffs_ramdisk.h yaffs_ramem2k.c \ - yaffsnewcfg.c yramsim.c yramsim.h \ - ynorsim.h ynorsim.c yaffs_osglue.c - -COPIED_SOURCES = $(YAFFSDIRECTSYMLINKS) $(DIRECTEXTRASYMLINKS) - -all: libyaffsfs.so - - -$(YAFFSLIBOBJS): %.o: %.c - gcc -c $(CFLAGS) -o $@ $< - - -$(YAFFSDIRECTSYMLINKS): - ln -s ../$@ $@ - -$(DIRECTEXTRASYMLINKS): - ln -s ../basic-test/$@ $@ - - -libyaffsfs.so: $(COPIED_SOURCES) $(YAFFSLIBOBJS) - gcc -shared $(YAFFSLIBOBJS) -o $@ - - -clean: - rm -f $(YAFFSLIBOBJS) core $(COPIED_SOURCES) - rm -f libyaffsfs.so - rm -f *.pyc diff --git a/direct/tests/Makefile b/direct/test-framework/FrameworkRules.mk similarity index 71% rename from direct/tests/Makefile rename to direct/test-framework/FrameworkRules.mk index 4f6e3c3..da47e49 100644 --- a/direct/tests/Makefile +++ b/direct/test-framework/FrameworkRules.mk @@ -1,4 +1,4 @@ -# Makefile for YAFFS direct stress tests +# Makefile rules for building in test framwork # # # YAFFS: Yet another Flash File System. A NAND-flash specific file system. @@ -14,13 +14,12 @@ # # NB Warning this Makefile does not include header dependencies. # -# $Id: Makefile,v 1.7 2010-02-25 22:34:47 charles Exp $ #EXTRA_COMPILE_FLAGS = -DYAFFS_IGNORE_TAGS_ECC CFLAGS = -DCONFIG_YAFFS_DIRECT -DCONFIG_YAFFS_YAFFS2 -DCONFIG_YAFFS_DEFINES_TYPES CFLAGS += -DCONFIG_YAFFS_PROVIDE_DEFS -DCONFIG_YAFFSFS_PROVIDE_VALUES -CFLAGS += -Wall -g $(EXTRA_COMPILE_FLAGS) -Wstrict-aliasing +CFLAGS += -Wall -g $(EXTRA_COMPILE_FLAGS) -Wstrict-aliasing #CFLAGS += -fno-strict-aliasing CFLAGS += -O0 CFLAGS += -Wextra -Wpointer-arith @@ -33,10 +32,11 @@ CFLAGS += -Wextra -Wpointer-arith COMMONTESTOBJS = yaffscfg2k.o yaffs_osglue.o yaffs_hweight.o\ yaffs_ecc.o yaffs_fileem.o yaffs_fileem2k.o yaffsfs.o yaffs_guts.o \ yaffs_packedtags1.o yaffs_ramdisk.o yaffs_ramem2k.o \ - yaffs_tagscompat.o yaffs_packedtags2.o yaffs_nand.o \ + yaffs_tagscompat.o yaffs_tagsmarshall.o \ + yaffs_packedtags2.o yaffs_nand.o \ yaffs_checkptrw.o yaffs_qsort.o\ yaffs_nameval.o yaffs_attribs.o \ - yaffs_norif1.o ynorsim.o nor_stress.o yaffs_fsx.o \ + yaffs_m18_drv.o ynorsim.o \ yaffs_allocator.o \ yaffs_bitmap.o \ yaffs_yaffs1.o \ @@ -44,12 +44,9 @@ COMMONTESTOBJS = yaffscfg2k.o yaffs_osglue.o yaffs_hweight.o\ yaffs_verify.o \ yaffs_summary.o -# yaffs_checkptrwtest.o\ -YAFFSTESTOBJS = $(COMMONTESTOBJS) yaffs_test.o - -ALLOBJS = $(sort $(YAFFSTESTOBJS)) +ALLOBJS = $(sort $(ALL_UNSORTED_OBJS)) YAFFSDIRECTSYMLINKS = \ yaffsfs.c yaffs_flashif.h yaffs_flashif2.h\ @@ -61,6 +58,7 @@ YAFFSDIRECTSYMLINKS = \ yaffs_hweight.c yaffs_hweight.h \ yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h \ yaffs_tagscompat.c yaffs_tagscompat.h \ + yaffs_tagsmarshall.c yaffs_tagsmarshall.h \ yaffs_packedtags1.c yaffs_packedtags1.h \ yaffs_packedtags2.c yaffs_packedtags2.h \ yaffs_nand.c yaffs_nand.h yaffs_getblockinfo.h \ @@ -75,31 +73,23 @@ YAFFSDIRECTSYMLINKS = \ yaffs_summary.c yaffs_summary.h -DIRECTEXTRASYMLINKS = yaffscfg2k.c yaffs_fileem2k.c yaffs_fileem2k.h\ - yaffs_fileem.c yaffs_norif1.c yaffs_norif1.h \ - yaffs_ramdisk.c yaffs_ramdisk.h yaffs_ramem2k.c \ - ynorsim.h ynorsim.c yaffs_osglue.c - -COPIED_SOURCES = $(YAFFSDIRECTSYMLINKS) $(DIRECTEXTRASYMLINKS) +FRAMEWORKEXTRASYMLINKS = \ + yaffscfg2k.c yaffs_fileem2k.c yaffs_fileem2k.h\ + yaffs_fileem.c yaffs_m18_drv.c yaffs_m18_drv.h \ + yaffs_ramdisk.c yaffs_ramdisk.h yaffs_ramem2k.c \ + ynorsim.h ynorsim.c yaffs_osglue.c -all: yaffs_test fuzzer - -$(ALLOBJS): %.o: %.c - gcc -c $(CFLAGS) -o $@ $< +FRAMEWORK_SOURCES = $(YAFFSDIRECTSYMLINKS) $(FRAMEWORKEXTRASYMLINKS) +clean: + rm -f $(TARGETS) $(ALLOBJS) core $(FRAMEWORK_SOURCES) $(YAFFSDIRECTSYMLINKS): - ln -s ../$@ $@ + ln -s $(YDI_DIR)/$@ $@ -$(DIRECTEXTRASYMLINKS): - ln -s ../basic-test/$@ $@ +$(FRAMEWORKEXTRASYMLINKS): + ln -s $(YDI_FRAMEWORK_DIR)/$@ $@ -yaffs_test: $(COPIED_SOURCES) $(YAFFSTESTOBJS) - gcc $(CFLLAG) -o $@ $(YAFFSTESTOBJS) - -fuzzer: fuzzer.c - gcc $(CFLAGS) -o $@ $< - -clean: - rm -f yaffs_test fuzzer fuzzer.o $(ALLOBJS) core $(COPIED_SOURCES) +$(ALLOBJS): %.o: %.c + gcc -c $(CFLAGS) -o $@ $< diff --git a/direct/test-framework/basic-tests/Makefile b/direct/test-framework/basic-tests/Makefile new file mode 100644 index 0000000..c1f3391 --- /dev/null +++ b/direct/test-framework/basic-tests/Makefile @@ -0,0 +1,36 @@ +# Makefile for YAFFS direct test +# +# +# YAFFS: Yet another Flash File System. A NAND-flash specific file system. +# +# Copyright (C) 2003-2010 Aleph One Ltd. +# +# +# Created by Charles Manning +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# NB Warning this Makefile does not include header dependencies. +# + + + + +YDI_DIR = ../../ +YDI_FRAMEWORK_DIR = ../ + +TARGETS = directtest2k + +all: $(TARGETS) + +DIRECTTESTOBJS = $(COMMONTESTOBJS) dtest.o + +ALL_UNSORTED_OBJS += $(DIRECTTESTOBJS) + +include ../FrameworkRules.mk + +directtest2k: $(FRAMEWORK_SOURCES) $(DIRECTTESTOBJS) + gcc -o $@ $(DIRECTTESTOBJS) + diff --git a/direct/basic-test/dtest.c b/direct/test-framework/basic-tests/dtest.c similarity index 100% rename from direct/basic-test/dtest.c rename to direct/test-framework/basic-tests/dtest.c diff --git a/direct/test-framework/python/Makefile b/direct/test-framework/python/Makefile new file mode 100644 index 0000000..9deee5e --- /dev/null +++ b/direct/test-framework/python/Makefile @@ -0,0 +1,72 @@ +# Makefile for YAFFS direct stress tests +# +# +# YAFFS: Yet another Flash File System. A NAND-flash specific file system. +# +# Copyright (C) 2003-2010 Aleph One Ltd. +# +# +# Created by Charles Manning +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# NB Warning this Makefile does not include header dependencies. +# + + + + + + + +$(YAFFSLIBOBJS): %.o: %.c + gcc -c $(CFLAGS) -o $@ $< + + +$(YAFFSDIRECTSYMLINKS): + ln -s ../$@ $@ + +$(DIRECTEXTRASYMLINKS): + ln -s ../basic-test/$@ $@ + + +# Makefile for stress tests and fuzzer +# +# +# YAFFS: Yet another Flash File System. A NAND-flash specific file system. +# +# Copyright (C) 2003-2010 Aleph One Ltd. +# +# +# Created by Charles Manning +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# NB Warning this Makefile does not include header dependencies. +# + +YDI_DIR = ../../ +YDI_FRAMEWORK_DIR = ../ + +TARGETS = libyaffsfs.so + + +all: $(TARGETS) + + +YAFFSLIBOBJS = $(COMMONTESTOBJS) yaffs_python_helper.o + +ALL_UNSORTED_OBJS += $(YAFFSLIBOBJS) + +include ../FrameworkRules.mk + +CFLAGS += -O0 -fPIC + + +libyaffsfs.so: $(FRAMEWORK_SOURCES) $(YAFFSLIBOBJS) + gcc -shared $(YAFFSLIBOBJS) -o $@ + diff --git a/direct/python/README.txt b/direct/test-framework/python/README.txt similarity index 100% rename from direct/python/README.txt rename to direct/test-framework/python/README.txt diff --git a/direct/python/README_yaffs_browser_py.txt b/direct/test-framework/python/README_yaffs_browser_py.txt similarity index 100% rename from direct/python/README_yaffs_browser_py.txt rename to direct/test-framework/python/README_yaffs_browser_py.txt diff --git a/direct/python/README_yaffs_import_py.txt b/direct/test-framework/python/README_yaffs_import_py.txt similarity index 100% rename from direct/python/README_yaffs_import_py.txt rename to direct/test-framework/python/README_yaffs_import_py.txt diff --git a/direct/python/examples.py b/direct/test-framework/python/examples.py similarity index 100% rename from direct/python/examples.py rename to direct/test-framework/python/examples.py diff --git a/direct/python/yaffs_browser.py b/direct/test-framework/python/yaffs_browser.py similarity index 100% rename from direct/python/yaffs_browser.py rename to direct/test-framework/python/yaffs_browser.py diff --git a/direct/python/yaffs_importer.py b/direct/test-framework/python/yaffs_importer.py similarity index 100% rename from direct/python/yaffs_importer.py rename to direct/test-framework/python/yaffs_importer.py diff --git a/direct/python/yaffs_python_helper.c b/direct/test-framework/python/yaffs_python_helper.c similarity index 100% rename from direct/python/yaffs_python_helper.c rename to direct/test-framework/python/yaffs_python_helper.c diff --git a/direct/python/yaffsfs.py b/direct/test-framework/python/yaffsfs.py similarity index 100% rename from direct/python/yaffsfs.py rename to direct/test-framework/python/yaffsfs.py diff --git a/direct/test-framework/tests/Makefile b/direct/test-framework/tests/Makefile new file mode 100644 index 0000000..cbfe151 --- /dev/null +++ b/direct/test-framework/tests/Makefile @@ -0,0 +1,37 @@ +# Makefile for stress tests and fuzzer +# +# +# YAFFS: Yet another Flash File System. A NAND-flash specific file system. +# +# Copyright (C) 2003-2010 Aleph One Ltd. +# +# +# Created by Charles Manning +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# NB Warning this Makefile does not include header dependencies. +# + +YDI_DIR = ../../ +YDI_FRAMEWORK_DIR = ../ + +TARGETS = yaffs_test fuzzer + +all: $(TARGETS) + +YAFFS_TEST_OBJS = $(COMMONTESTOBJS) yaffs_test.o nor_stress.o yaffs_fsx.o +FUZZER_OBJS = fuzzer.o + +ALL_UNSORTED_OBJS += $(YAFFS_TEST_OBJS) $(FUZZER_OBJS) + +include ../FrameworkRules.mk + + +yaffs_test: $(FRAMEWORK_SOURCES) $(YAFFS_TEST_OBJS) + gcc $(CFLLAG) -o $@ $(YAFFS_TEST_OBJS) + +fuzzer: $(FUZZER_OBJS) + gcc $(CFLAGS) -o $@ $< diff --git a/direct/tests/README b/direct/test-framework/tests/README similarity index 100% rename from direct/tests/README rename to direct/test-framework/tests/README diff --git a/direct/tests/fuzzer.c b/direct/test-framework/tests/fuzzer.c similarity index 100% rename from direct/tests/fuzzer.c rename to direct/test-framework/tests/fuzzer.c diff --git a/direct/tests/init_fw_update_test_nand.sh b/direct/test-framework/tests/init_fw_update_test_nand.sh similarity index 100% rename from direct/tests/init_fw_update_test_nand.sh rename to direct/test-framework/tests/init_fw_update_test_nand.sh diff --git a/direct/tests/init_fw_update_test_nor.sh b/direct/test-framework/tests/init_fw_update_test_nor.sh similarity index 100% rename from direct/tests/init_fw_update_test_nor.sh rename to direct/test-framework/tests/init_fw_update_test_nor.sh diff --git a/direct/tests/launch_tests.sh b/direct/test-framework/tests/launch_tests.sh similarity index 100% rename from direct/tests/launch_tests.sh rename to direct/test-framework/tests/launch_tests.sh diff --git a/direct/tests/manage_nand_test.sh b/direct/test-framework/tests/manage_nand_test.sh similarity index 100% rename from direct/tests/manage_nand_test.sh rename to direct/test-framework/tests/manage_nand_test.sh diff --git a/direct/tests/manage_nor_test.sh b/direct/test-framework/tests/manage_nor_test.sh similarity index 100% rename from direct/tests/manage_nor_test.sh rename to direct/test-framework/tests/manage_nor_test.sh diff --git a/direct/tests/nor_stress.c b/direct/test-framework/tests/nor_stress.c similarity index 100% rename from direct/tests/nor_stress.c rename to direct/test-framework/tests/nor_stress.c diff --git a/direct/tests/nor_stress.h b/direct/test-framework/tests/nor_stress.h similarity index 100% rename from direct/tests/nor_stress.h rename to direct/test-framework/tests/nor_stress.h diff --git a/direct/tests/run_fuzz_test_nand.sh b/direct/test-framework/tests/run_fuzz_test_nand.sh similarity index 100% rename from direct/tests/run_fuzz_test_nand.sh rename to direct/test-framework/tests/run_fuzz_test_nand.sh diff --git a/direct/tests/run_fw_update_test_nand.sh b/direct/test-framework/tests/run_fw_update_test_nand.sh similarity index 100% rename from direct/tests/run_fw_update_test_nand.sh rename to direct/test-framework/tests/run_fw_update_test_nand.sh diff --git a/direct/tests/run_fw_update_test_nor.sh b/direct/test-framework/tests/run_fw_update_test_nor.sh similarity index 100% rename from direct/tests/run_fw_update_test_nor.sh rename to direct/test-framework/tests/run_fw_update_test_nor.sh diff --git a/direct/tests/yaffs_fsx.c b/direct/test-framework/tests/yaffs_fsx.c similarity index 100% rename from direct/tests/yaffs_fsx.c rename to direct/test-framework/tests/yaffs_fsx.c diff --git a/direct/tests/yaffs_fsx.h b/direct/test-framework/tests/yaffs_fsx.h similarity index 100% rename from direct/tests/yaffs_fsx.h rename to direct/test-framework/tests/yaffs_fsx.h diff --git a/direct/tests/yaffs_test.c b/direct/test-framework/tests/yaffs_test.c similarity index 100% rename from direct/tests/yaffs_test.c rename to direct/test-framework/tests/yaffs_test.c diff --git a/direct/basic-test/yaffs_fileem.c b/direct/test-framework/yaffs_fileem.c similarity index 97% rename from direct/basic-test/yaffs_fileem.c rename to direct/test-framework/yaffs_fileem.c index 267e134..96a64c6 100644 --- a/direct/basic-test/yaffs_fileem.c +++ b/direct/test-framework/yaffs_fileem.c @@ -16,9 +16,6 @@ * This is only intended as test code to test persistence etc. */ -const char *yaffs_flashif_c_version = "$Id: yaffs_fileem.c,v 1.7 2010-02-18 01:18:04 charles Exp $"; - - #include "yportenv.h" #include "yaffs_trace.h" diff --git a/direct/test-framework/yaffs_fileem2k.c b/direct/test-framework/yaffs_fileem2k.c new file mode 100644 index 0000000..b9a00f1 --- /dev/null +++ b/direct/test-framework/yaffs_fileem2k.c @@ -0,0 +1,400 @@ +/* + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. + * + * Copyright (C) 2002-2011 Aleph One Ltd. + * for Toby Churchill Ltd and Brightstar Engineering + * + * Created by Charles Manning + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* + * This provides a YAFFS nand emulation on a file for emulating 2kB pages. + * This is only intended as test code to test persistence etc. + */ + +#include "yportenv.h" +#include "yaffs_trace.h" + +#include "yaffs_flashif2.h" +#include "yaffs_guts.h" +#include "yaffs_fileem2k.h" +#include "yaffs_packedtags2.h" + + +#include +#include +#include +#include + +#if 1 + +#define SIZE_IN_MB 32 +/* #define SIZE_IN_MB 128 */ + +#define PAGE_DATA_SIZE (2048) +#define PAGE_SPARE_SIZE (64) +#define PAGE_SIZE (PAGE_DATA_SIZE + PAGE_SPARE_SIZE) +#define PAGES_PER_BLOCK (64) +#define BLOCK_DATA_SIZE (PAGE_DATA_SIZE * PAGES_PER_BLOCK) +#define BLOCK_SIZE (PAGES_PER_BLOCK * (PAGE_SIZE)) +#define BLOCKS_PER_MB ((1024*1024)/BLOCK_DATA_SIZE) +#define SIZE_IN_BLOCKS (BLOCKS_PER_MB * SIZE_IN_MB) + +#else + +#define SIZE_IN_MB 128 +#define PAGE_DATA_SIZE (512) +#define SPARE_SIZE (16) +#define PAGE_SIZE (PAGE_DATA_SIZE + SPARE_SIZE) +#define PAGES_PER_BLOCK (32) +#define BLOCK_DATA_SIZE (PAGE_SIZE * PAGES_PER_BLOCK) +#define BLOCK_SIZE (PAGES_PER_BLOCK * (PAGE_SIZE)) +#define BLOCKS_PER_MB ((1024*1024)/BLOCK_DATA_SIZE) +#define SIZE_IN_BLOCKS (BLOCKS_PER_MB * SIZE_IN_MB) + +#endif + +#define REPORT_ERROR 0 + +typedef struct +{ + u8 data[PAGE_SIZE]; // Data + spare +} yflash_Page; + +typedef struct +{ + yflash_Page page[PAGES_PER_BLOCK]; // The pages in the block + +} yflash_Block; + + + +#define MAX_HANDLES 20 +#define BLOCKS_PER_HANDLE (32*8) + +typedef struct +{ + int handle[MAX_HANDLES]; + int nBlocks; +} yflash_Device; + +static yflash_Device filedisk; + +int yaffs_test_partial_write = 0; + +extern int random_seed; +extern int simulate_power_failure; +static int remaining_ops; +static int nops_so_far; + +int ops_multiplier; + + +static void yflash2_MaybePowerFail(unsigned int nand_chunk, int failPoint) +{ + + nops_so_far++; + + + remaining_ops--; + if(simulate_power_failure && + remaining_ops < 1){ + printf("Simulated power failure after %d operations\n",nops_so_far); + printf(" power failed on nand_chunk %d, at fail point %d\n", + nand_chunk, failPoint); + exit(0); + } +} + + + + + +static u8 localBuffer[PAGE_SIZE]; + +static char *NToName(char *buf,int n) +{ + sprintf(buf,"emfile-2k-%d",n); + return buf; +} + +static char dummyBuffer[BLOCK_SIZE]; + +static int GetBlockFileHandle(int n) +{ + int h; + int requiredSize; + + char name[40]; + NToName(name,n); + int fSize; + int i; + + h = open(name, O_RDWR | O_CREAT, S_IREAD | S_IWRITE); + if(h >= 0){ + fSize = lseek(h,0,SEEK_END); + requiredSize = BLOCKS_PER_HANDLE * BLOCK_SIZE; + if(fSize < requiredSize){ + for(i = 0; i < BLOCKS_PER_HANDLE; i++) + if(write(h,dummyBuffer,BLOCK_SIZE) != BLOCK_SIZE) + return -1; + + } + } + + return h; + +} + +static int CheckInit(void) +{ + static int initialised = 0; + int i; + + int blk; + + + if(initialised) + { + return YAFFS_OK; + } + + initialised = 1; + + + srand(random_seed); + remaining_ops = (rand() % 1000) * 5; + memset(dummyBuffer,0xff,sizeof(dummyBuffer)); + + + + filedisk.nBlocks = SIZE_IN_MB * BLOCKS_PER_MB; + + for(i = 0; i < MAX_HANDLES; i++) + filedisk.handle[i] = -1; + + for(i = 0,blk = 0; blk < filedisk.nBlocks; blk+=BLOCKS_PER_HANDLE,i++) + filedisk.handle[i] = GetBlockFileHandle(i); + + + return 1; +} + + +int yflash2_GetNumberOfBlocks(void) +{ + CheckInit(); + + return filedisk.nBlocks; +} + + +int yaffs_check_all_ff(const u8 *ptr, int n) +{ + while(n) + { + n--; + if(*ptr!=0xFF) return 0; + ptr++; + } + return 1; +} + + +static int yflash2_WriteChunk(struct yaffs_dev *dev, int nand_chunk, + const u8 *data, int data_len, + const u8 *oob, int oob_len) +{ + int retval = YAFFS_OK; + int pos; + int h; + int nwritten; + + (void) dev; + + if (data && data_len) { + pos = (nand_chunk % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE; + h = filedisk.handle[(nand_chunk / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))]; + lseek(h,pos,SEEK_SET); + nwritten = write(h,data,data_len); + if(nwritten != data_len) + retval = YAFFS_FAIL; + } + + if (oob && oob_len) { + pos = (nand_chunk % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE + PAGE_DATA_SIZE; + h = filedisk.handle[(nand_chunk / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))]; + lseek(h,pos,SEEK_SET); + nwritten = write(h,oob,oob_len); + if(nwritten != oob_len) + retval = YAFFS_FAIL; + } + + yflash2_MaybePowerFail(nand_chunk,3); + + return retval; +} + +static int yflash2_ReadChunk(struct yaffs_dev *dev, int nand_chunk, + u8 *data, int data_len, + u8 *oob, int oob_len, + enum yaffs_ecc_result *ecc_result) +{ + int retval = YAFFS_OK; + int pos; + int h; + int nread; + + (void) dev; + + if (data && data_len) { + pos = (nand_chunk % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE; + h = filedisk.handle[(nand_chunk / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))]; + lseek(h,pos,SEEK_SET); + nread = read(h,data,data_len); + if(nread != data_len) + retval = YAFFS_FAIL; + } + + if (oob && oob_len) { + pos = (nand_chunk % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE + PAGE_DATA_SIZE; + h = filedisk.handle[(nand_chunk / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))]; + lseek(h,pos,SEEK_SET); + nread = read(h,oob,oob_len); + if(nread != oob_len) + retval = YAFFS_FAIL; + } + + if (ecc_result) + *ecc_result = YAFFS_ECC_RESULT_NO_ERROR; + + return retval; +} + +static int yflash2_EraseBlock(struct yaffs_dev *dev, int block_no) +{ + int i; + int h; + + CheckInit(); + + if(block_no < 0 || block_no >= filedisk.nBlocks) + { + yaffs_trace(YAFFS_TRACE_ALWAYS,"Attempt to erase non-existant block %d",block_no); + return YAFFS_FAIL; + } + else + { + + u8 pg[PAGE_SIZE]; + int syz = PAGE_SIZE; + int pos; + + memset(pg,0xff,syz); + + + h = filedisk.handle[(block_no / ( BLOCKS_PER_HANDLE))]; + lseek(h,((block_no % BLOCKS_PER_HANDLE) * dev->param.chunks_per_block) * PAGE_SIZE,SEEK_SET); + for(i = 0; i < dev->param.chunks_per_block; i++) + { + write(h,pg,PAGE_SIZE); + } + pos = lseek(h, 0,SEEK_CUR); + + return YAFFS_OK; + } +} + +static int yflash2_MarkBad(struct yaffs_dev *dev, int block_no) +{ + int written; + int h; + + struct yaffs_packed_tags2 pt; + + CheckInit(); + + memset(&pt,0,sizeof(pt)); + h = filedisk.handle[(block_no / ( BLOCKS_PER_HANDLE))]; + lseek(h,((block_no % BLOCKS_PER_HANDLE) * dev->param.chunks_per_block) * PAGE_SIZE + PAGE_DATA_SIZE,SEEK_SET); + written = write(h,&pt,sizeof(pt)); + + if(written != sizeof(pt)) + return YAFFS_FAIL; + + return YAFFS_OK; + +} + +static int yflash2_CheckBad(struct yaffs_dev *dev, int block_no) +{ + (void) dev; + (void) block_no; + + return YAFFS_OK; +} + +static int yflash2_Initialise(struct yaffs_dev *dev) +{ + (void) dev; + + CheckInit(); + + return YAFFS_OK; +} + +struct yaffs_dev *yflash2_install_drv(const char *name) +{ + struct yaffs_dev *dev = NULL; + struct yaffs_param *param; + struct yaffs_driver *drv; + + dev = malloc(sizeof(*dev)); + + if(!dev) + return NULL; + + memset(dev, 0, sizeof(*dev)); + + dev->param.name = strdup(name); + + if(!dev->param.name) { + free(dev); + return NULL; + } + + drv = &dev->drv; + + drv->drv_write_chunk_fn = yflash2_WriteChunk; + drv->drv_read_chunk_fn = yflash2_ReadChunk; + drv->drv_erase_fn = yflash2_EraseBlock; + drv->drv_mark_bad_fn = yflash2_MarkBad; + drv->drv_check_bad_fn = yflash2_CheckBad; + drv->drv_initialise_fn = yflash2_Initialise; + + param = &dev->param; + + param->total_bytes_per_chunk = 2048; + param->chunks_per_block = 64; + param->start_block = 0; + param->end_block = yflash2_GetNumberOfBlocks()-1; + param->is_yaffs2 = 1; + param->use_nand_ecc=1; + + param->n_reserved_blocks = 5; + param->wide_tnodes_disabled=0; + param->refresh_period = 1000; + param->n_caches = 10; // Use caches + + param->enable_xattr = 1; + + /* dev->driver_context is not used by this simulator */ + + yaffs_add_device(dev); + + return dev; +} diff --git a/direct/test-framework/yaffs_fileem2k.h b/direct/test-framework/yaffs_fileem2k.h new file mode 100644 index 0000000..b7234c0 --- /dev/null +++ b/direct/test-framework/yaffs_fileem2k.h @@ -0,0 +1,26 @@ +/* + * YAFFS: Yet another Flash File System . A NAND-flash specific file system. + * + * Copyright (C) 2002-2011 Aleph One Ltd. + * for Toby Churchill Ltd and Brightstar Engineering + * + * Created by Charles Manning + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 2.1 as + * published by the Free Software Foundation. + * + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. + */ + +#ifndef __FILEEM2K_H__ +#define __FILEEM2K_H__ + + +struct yaffs_dev; + +struct yaffs_dev *yflash2_install_drv(const char *name); + + +#endif + diff --git a/direct/basic-test/yaffs_norif1.c b/direct/test-framework/yaffs_m18_drv.c similarity index 56% rename from direct/basic-test/yaffs_norif1.c rename to direct/test-framework/yaffs_m18_drv.c index 98008b5..0325968 100644 --- a/direct/basic-test/yaffs_norif1.c +++ b/direct/test-framework/yaffs_m18_drv.c @@ -17,27 +17,25 @@ /* First set up for M18 with 1k chunks and 16-byte spares. * - * NB We're using the oddball M18 modes of operation here + * NB We're using the oddball M18 modes of operation here * The chip is 64MB based at 0x0000, but YAFFS only going to use the top half * ie. YAFFS will be from 32MB to 64MB. * - * The M18 has two ways of writing data. Every Programming Region (1kbytes) + * The M18 has two ways of writing data. Every Programming Region (1kbytes) * can be programmed in two modes: * * Object Mode 1024 bytes of write once data. - * * Control Mode: 512bytes of bit-writeable data. + * * Control Mode: 512bytes of bit-writeable data. * This is arranged as 32 * (16 bytes of bit-writable followed by 16 bytes of "dont touch") - * + * * The block size is 256kB, making 128 blocks in the 32MB YAFFS area. * Each block comprises: * Offset 0k: 248 x 1k data pages * Offset 248k: 248 x 32-byte spare areas implemented as 16 bytes of spare followed by 16 bytes untouched) * Offset 248k + (248 * 32): Format marker - * + * */ -const char *yaffs_norif1_c_version = "$Id: yaffs_norif1.c,v 1.6 2010-02-18 01:18:04 charles Exp $"; - -#include "yaffs_norif1.h" +#include "yaffs_m18_drv.h" #include "yportenv.h" #include "yaffs_trace.h" @@ -52,7 +50,8 @@ const char *yaffs_norif1_c_version = "$Id: yaffs_norif1.c,v 1.6 2010-02-18 01:18 #define CHUNKS_PER_BLOCK 248 #define SPARE_AREA_OFFSET (CHUNKS_PER_BLOCK * PROG_REGION_SIZE) -#define FORMAT_OFFSET (SPARE_AREA_OFFSET + CHUNKS_PER_BLOCK * (SPARE_BYTES_PER_CHUNK + M18_SKIP)) +#define FORMAT_OFFSET (SPARE_AREA_OFFSET + CHUNKS_PER_BLOCK * \ + (SPARE_BYTES_PER_CHUNK + M18_SKIP)) #define FORMAT_VALUE 0x1234 @@ -68,68 +67,69 @@ const char *yaffs_norif1_c_version = "$Id: yaffs_norif1.c,v 1.6 2010-02-18 01:18 /* Compile this for a simulation */ #include "ynorsim.h" -#define ynorif1_FlashInit() ynorsim_initialise() -#define ynorif1_FlashDeinit() ynorsim_shutdown() -#define ynorif1_FlashWrite32(addr,buf,nwords) ynorsim_wr32(addr,buf,nwords) -#define ynorif1_FlashRead32(addr,buf,nwords) ynorsim_rd32(addr,buf,nwords) -#define ynorif1_FlashEraseBlock(addr) ynorsim_erase(addr) +#define m18_drv_FlashInit() ynorsim_initialise() +#define m18_drv_FlashDeinit() ynorsim_shutdown() +#define m18_drv_FlashWrite32(addr,buf,nwords) ynorsim_wr32(addr,buf,nwords) +#define m18_drv_FlashRead32(addr,buf,nwords) ynorsim_rd32(addr,buf,nwords) +#define m18_drv_FlashEraseBlock(addr) ynorsim_erase(addr) #define DEVICE_BASE ynorsim_get_base() #else -/* Compile this for running on blob, hacked for yaffs access */ +/* Compile this to hook up to read hardware */ #include "../blob/yflashrw.h" -#define ynorif1_FlashInit() do{} while(0) -#define ynorif1_FlashDeinit() do {} while(0) -#define ynorif1_FlashWrite32(addr,buf,nwords) Y_FlashWrite(addr,buf,nwords) -#define ynorif1_FlashRead32(addr,buf,nwords) Y_FlashRead(addr,buf,nwords) -#define ynorif1_FlashEraseBlock(addr) Y_FlashErase(addr,BLOCK_SIZE_IN_BYTES) +#define m18_drv_FlashInit() do{} while(0) +#define m18_drv_FlashDeinit() do {} while(0) +#define m18_drv_FlashWrite32(addr,buf,nwords) Y_FlashWrite(addr,buf,nwords) +#define m18_drv_FlashRead32(addr,buf,nwords) Y_FlashRead(addr,buf,nwords) +#define m18_drv_FlashEraseBlock(addr) Y_FlashErase(addr,BLOCK_SIZE_IN_BYTES) #define DEVICE_BASE (32 * 1024 * 1024) #endif -u32 *Block2Addr(struct yaffs_dev *dev, int blockNumber) +static u32 *Block2Addr(struct yaffs_dev *dev, int blockNumber) { u32 addr; dev=dev; - + addr = (u32) DEVICE_BASE; addr += blockNumber * BLOCK_SIZE_IN_BYTES; - + return (u32 *) addr; } -u32 *Block2FormatAddr(struct yaffs_dev *dev,int blockNumber) +static u32 *Block2FormatAddr(struct yaffs_dev *dev,int blockNumber) { u32 addr; addr = (u32) Block2Addr(dev,blockNumber); addr += FORMAT_OFFSET; - + return (u32 *)addr; } -u32 *Chunk2DataAddr(struct yaffs_dev *dev,int chunk_id) + +static u32 *Chunk2DataAddr(struct yaffs_dev *dev,int chunk_id) { unsigned block; unsigned chunkInBlock; u32 addr; - + block = chunk_id/dev->param.chunks_per_block; chunkInBlock = chunk_id % dev->param.chunks_per_block; - + addr = (u32) Block2Addr(dev,block); addr += chunkInBlock * DATA_BYTES_PER_CHUNK; - + return (u32 *)addr; } -u32 *Chunk2SpareAddr(struct yaffs_dev *dev,int chunk_id) +static u32 *Chunk2SpareAddr(struct yaffs_dev *dev,int chunk_id) { unsigned block; unsigned chunkInBlock; u32 addr; - + block = chunk_id/dev->param.chunks_per_block; chunkInBlock = chunk_id % dev->param.chunks_per_block; - + addr = (u32) Block2Addr(dev,block); addr += SPARE_AREA_OFFSET; addr += chunkInBlock * (SPARE_BYTES_PER_CHUNK + M18_SKIP); @@ -137,7 +137,7 @@ u32 *Chunk2SpareAddr(struct yaffs_dev *dev,int chunk_id) } -void ynorif1_AndBytes(u8*target, const u8 *src, int nbytes) +static void m18_drv_AndBytes(u8*target, const u8 *src, int nbytes) { while(nbytes > 0){ *target &= *src; @@ -147,78 +147,87 @@ void ynorif1_AndBytes(u8*target, const u8 *src, int nbytes) } } -int ynorif1_WriteChunkToNAND(struct yaffs_dev *dev,int nand_chunk,const u8 *data, const struct yaffs_spare *spare) +static int m18_drv_WriteChunkToNAND(struct yaffs_dev *dev,int nand_chunk, + const u8 *data, int data_len, + const u8 *oob, int oob_len) { u32 *dataAddr = Chunk2DataAddr(dev,nand_chunk); u32 *spareAddr = Chunk2SpareAddr(dev,nand_chunk); - + + struct yaffs_spare *spare = (struct yaffs_spare *)oob; struct yaffs_spare tmpSpare; - + + (void) oob_len; + /* We should only be getting called for one of 3 reasons: * Writing a chunk: data and spare will not be NULL * Writing a deletion marker: data will be NULL, spare not NULL * Writing a bad block marker: data will be NULL, spare not NULL */ - + if(sizeof(struct yaffs_spare) != 16) BUG(); - - if(data && spare) + + if(data && oob) { if(spare->page_status != 0xff) BUG(); /* Write a pre-marker */ memset(&tmpSpare,0xff,sizeof(tmpSpare)); tmpSpare.page_status = YNOR_PREMARKER; - ynorif1_FlashWrite32(spareAddr,(u32 *)&tmpSpare,sizeof(struct yaffs_spare)/4); + m18_drv_FlashWrite32(spareAddr,(u32 *)&tmpSpare,sizeof(struct yaffs_spare)/4); + + /* Write the data */ + m18_drv_FlashWrite32(dataAddr,(u32 *)data, data_len/ 4); + - /* Write the data */ - ynorif1_FlashWrite32(dataAddr,(u32 *)data,dev->param.total_bytes_per_chunk / 4); - - memcpy(&tmpSpare,spare,sizeof(struct yaffs_spare)); - + /* Write the real tags, but override the premarker*/ tmpSpare.page_status = YNOR_PREMARKER; - ynorif1_FlashWrite32(spareAddr,(u32 *)&tmpSpare,sizeof(struct yaffs_spare)/4); - + m18_drv_FlashWrite32(spareAddr,(u32 *)&tmpSpare,sizeof(struct yaffs_spare)/4); + /* Write a post-marker */ tmpSpare.page_status = YNOR_POSTMARKER; - ynorif1_FlashWrite32(spareAddr,(u32 *)&tmpSpare,sizeof(tmpSpare)/4); + m18_drv_FlashWrite32(spareAddr,(u32 *)&tmpSpare,sizeof(tmpSpare)/4); } else if(spare){ /* This has to be a read-modify-write operation to handle NOR-ness */ - ynorif1_FlashRead32(spareAddr,(u32 *)&tmpSpare,16/ 4); - - ynorif1_AndBytes((u8 *)&tmpSpare,(u8 *)spare,sizeof(struct yaffs_spare)); - - ynorif1_FlashWrite32(spareAddr,(u32 *)&tmpSpare,16/ 4); + m18_drv_FlashRead32(spareAddr,(u32 *)&tmpSpare,16/ 4); + + m18_drv_AndBytes((u8 *)&tmpSpare,(u8 *)spare,sizeof(struct yaffs_spare)); + + m18_drv_FlashWrite32(spareAddr,(u32 *)&tmpSpare,16/ 4); } else { BUG(); } - - return YAFFS_OK; + + return YAFFS_OK; } -int ynorif1_ReadChunkFromNAND(struct yaffs_dev *dev,int nand_chunk, u8 *data, struct yaffs_spare *spare) +static int m18_drv_ReadChunkFromNAND(struct yaffs_dev *dev,int nand_chunk, + u8 *data, int data_len, + u8 *oob, int oob_len, + enum yaffs_ecc_result *ecc_result) { + struct yaffs_spare *spare = (struct yaffs_spare *)oob; u32 *dataAddr = Chunk2DataAddr(dev,nand_chunk); u32 *spareAddr = Chunk2SpareAddr(dev,nand_chunk); - + if(data) { - ynorif1_FlashRead32(dataAddr,(u32 *)data,dev->param.total_bytes_per_chunk / 4); + m18_drv_FlashRead32(dataAddr,(u32 *)data,dev->param.total_bytes_per_chunk / 4); } - - if(spare) + + if(oob) { - ynorif1_FlashRead32(spareAddr,(u32 *)spare,16/ 4); - + m18_drv_FlashRead32(spareAddr,(u32 *)spare, oob_len/ 4); + /* If the page status is YNOR_POSTMARKER then it was written properly * so change that to 0xFF so that the rest of yaffs is happy. */ @@ -228,46 +237,49 @@ int ynorif1_ReadChunkFromNAND(struct yaffs_dev *dev,int nand_chunk, u8 *data, st (spare->page_status | YNOR_PREMARKER) != 0xff) spare->page_status = YNOR_PREMARKER; } - - return YAFFS_OK; + if(ecc_result) + *ecc_result = YAFFS_ECC_RESULT_NO_ERROR; + + return YAFFS_OK; } -static int ynorif1_FormatBlock(struct yaffs_dev *dev, int blockNumber) + +static int m18_drv_FormatBlock(struct yaffs_dev *dev, int blockNumber) { u32 *blockAddr = Block2Addr(dev,blockNumber); u32 *formatAddr = Block2FormatAddr(dev,blockNumber); u32 formatValue = FORMAT_VALUE; - - ynorif1_FlashEraseBlock(blockAddr); - ynorif1_FlashWrite32(formatAddr,&formatValue,1); - + + m18_drv_FlashEraseBlock(blockAddr); + m18_drv_FlashWrite32(formatAddr,&formatValue,1); + return YAFFS_OK; } -static int ynorif1_UnformatBlock(struct yaffs_dev *dev, int blockNumber) +static int m18_drv_UnformatBlock(struct yaffs_dev *dev, int blockNumber) { u32 *formatAddr = Block2FormatAddr(dev,blockNumber); u32 formatValue = 0; - - ynorif1_FlashWrite32(formatAddr,&formatValue,1); - + + m18_drv_FlashWrite32(formatAddr,&formatValue,1); + return YAFFS_OK; } -static int ynorif1_IsBlockFormatted(struct yaffs_dev *dev, int blockNumber) +static int m18_drv_IsBlockFormatted(struct yaffs_dev *dev, int blockNumber) { u32 *formatAddr = Block2FormatAddr(dev,blockNumber); u32 formatValue; - - - ynorif1_FlashRead32(formatAddr,&formatValue,1); - + + + m18_drv_FlashRead32(formatAddr,&formatValue,1); + return (formatValue == FORMAT_VALUE); } -int ynorif1_EraseBlockInNAND(struct yaffs_dev *dev, int blockNumber) +static int m18_drv_EraseBlockInNAND(struct yaffs_dev *dev, int blockNumber) { if(blockNumber < 0 || blockNumber >= BLOCKS_IN_DEVICE) @@ -279,33 +291,77 @@ int ynorif1_EraseBlockInNAND(struct yaffs_dev *dev, int blockNumber) } else { - ynorif1_UnformatBlock(dev,blockNumber); - ynorif1_FormatBlock(dev,blockNumber); + m18_drv_UnformatBlock(dev,blockNumber); + m18_drv_FormatBlock(dev,blockNumber); return YAFFS_OK; } - + } -int ynorif1_InitialiseNAND(struct yaffs_dev *dev) +static int m18_drv_InitialiseNAND(struct yaffs_dev *dev) { int i; - - ynorif1_FlashInit(); + + m18_drv_FlashInit(); /* Go through the blocks formatting them if they are not formatted */ for(i = dev->param.start_block; i <= dev->param.end_block; i++){ - if(!ynorif1_IsBlockFormatted(dev,i)){ - ynorif1_FormatBlock(dev,i); + if(!m18_drv_IsBlockFormatted(dev,i)){ + m18_drv_FormatBlock(dev,i); } } return YAFFS_OK; } -int ynorif1_Deinitialise_flash_fn(struct yaffs_dev *dev) +static int m18_drv_Deinitialise_flash_fn(struct yaffs_dev *dev) { - dev=dev; - ynorif1_FlashDeinit(); + dev=dev; + m18_drv_FlashDeinit(); return YAFFS_OK; } +struct yaffs_dev *yaffs_m18_install_drv(const char *name) +{ + + struct yaffs_dev *dev = malloc(sizeof(struct yaffs_dev)); + char *name_copy = strdup(name); + struct yaffs_param *param; + struct yaffs_driver *drv; + + + if(!dev || !name_copy) { + free(name_copy); + free(dev); + return NULL; + } + + param = &dev->param; + drv = &dev->drv; + + memset(dev, 0, sizeof(*dev)); + + param->name = name_copy; + + param->total_bytes_per_chunk = 1024; + param->chunks_per_block =248; + param->n_reserved_blocks = 2; + param->start_block = 0; // Can use block 0 + param->end_block = 31; // Last block + param->use_nand_ecc = 0; // use YAFFS's ECC + + drv->drv_write_chunk_fn = m18_drv_WriteChunkToNAND; + drv->drv_read_chunk_fn = m18_drv_ReadChunkFromNAND; + drv->drv_erase_fn = m18_drv_EraseBlockInNAND; + drv->drv_initialise_fn = m18_drv_InitialiseNAND; + drv->drv_deinitialise_fn = m18_drv_Deinitialise_flash_fn; + + param->n_caches = 10; + param->disable_soft_del = 1; + + dev->driver_context = (void *) 1; // Used to identify the device in fstat. + + yaffs_add_device(dev); + + return NULL; +} diff --git a/direct/test-framework/yaffs_m18_drv.h b/direct/test-framework/yaffs_m18_drv.h new file mode 100644 index 0000000..7befb1a --- /dev/null +++ b/direct/test-framework/yaffs_m18_drv.h @@ -0,0 +1,25 @@ +/* + * YAFFS: Yet another Flash File System . A NAND-flash specific file system. + * + * Copyright (C) 2002-2011 Aleph One Ltd. + * for Toby Churchill Ltd and Brightstar Engineering + * + * Created by Charles Manning + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 2.1 as + * published by the Free Software Foundation. + * + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. + */ + + +#ifndef __YAFFS_M18_DRV_H__ +#define __YAFFS_M18_DRV_H__ + +struct yaffs_dev; +struct yaffs_dev *yaffs_m18_install_drv(const char *name); + +#endif + + diff --git a/direct/basic-test/yaffs_osglue.c b/direct/test-framework/yaffs_osglue.c similarity index 94% rename from direct/basic-test/yaffs_osglue.c rename to direct/test-framework/yaffs_osglue.c index 4a149e2..40e4052 100644 --- a/direct/basic-test/yaffs_osglue.c +++ b/direct/test-framework/yaffs_osglue.c @@ -15,9 +15,6 @@ #include "yaffscfg.h" #include "yaffs_guts.h" #include "yaffsfs.h" -#include "yaffs_fileem2k.h" -#include "yaffs_nandemul2k.h" -#include "yaffs_norif1.h" #include "yaffs_trace.h" #include @@ -37,6 +34,13 @@ int yaffsfs_GetLastError(void) return yaffsfs_lastError; } +int yaffsfs_CheckMemRegion(const void *addr, size_t size, int writeable) +{ + if(!addr) + return -1; + return 0; +} + #ifdef CONFIG_YAFFS_USE_PTHREADS #include diff --git a/direct/basic-test/yaffs_ramdisk.c b/direct/test-framework/yaffs_ramdisk.c similarity index 97% rename from direct/basic-test/yaffs_ramdisk.c rename to direct/test-framework/yaffs_ramdisk.c index bea5cfb..3d71e51 100644 --- a/direct/basic-test/yaffs_ramdisk.c +++ b/direct/test-framework/yaffs_ramdisk.c @@ -18,9 +18,6 @@ * Use this with dev->use_nand_ecc enabled, then ECC overheads are not required. */ -const char *yaffs_ramdisk_c_version = "$Id: yaffs_ramdisk.c,v 1.6 2010-01-11 04:06:47 charles Exp $"; - - #include "yportenv.h" #include "yaffs_trace.h" diff --git a/direct/basic-test/yaffs_ramdisk.h b/direct/test-framework/yaffs_ramdisk.h similarity index 100% rename from direct/basic-test/yaffs_ramdisk.h rename to direct/test-framework/yaffs_ramdisk.h diff --git a/direct/basic-test/yaffs_ramem2k.c b/direct/test-framework/yaffs_ramem2k.c similarity index 98% rename from direct/basic-test/yaffs_ramem2k.c rename to direct/test-framework/yaffs_ramem2k.c index 5bd0aff..715ae77 100644 --- a/direct/basic-test/yaffs_ramem2k.c +++ b/direct/test-framework/yaffs_ramem2k.c @@ -16,8 +16,6 @@ */ -const char *yaffs_ramem2k_c_version = "$Id: yaffs_ramem2k.c,v 1.8 2010-02-18 01:18:04 charles Exp $"; - #ifndef __KERNEL__ #define CONFIG_YAFFS_RAM_ENABLED #else diff --git a/direct/basic-test/yaffscfg.c b/direct/test-framework/yaffscfg.c similarity index 100% rename from direct/basic-test/yaffscfg.c rename to direct/test-framework/yaffscfg.c diff --git a/direct/test-framework/yaffscfg2k.c b/direct/test-framework/yaffscfg2k.c new file mode 100644 index 0000000..b9a09a7 --- /dev/null +++ b/direct/test-framework/yaffscfg2k.c @@ -0,0 +1,74 @@ +/* + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. + * + * Copyright (C) 2002-2011 Aleph One Ltd. + * for Toby Churchill Ltd and Brightstar Engineering + * + * Created by Charles Manning + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* + * yaffscfg2k.c The configuration for the "direct" use of yaffs. + * + * This file is intended to be modified to your requirements. + * There is no need to redistribute this file. + */ + +#include "yaffscfg.h" +#include "yaffs_guts.h" +#include "yaffsfs.h" +#include "yaffs_fileem2k.h" +#include "yaffs_nandemul2k.h" +#include "yaffs_trace.h" +#include "yaffs_osglue.h" + + +#include + +unsigned yaffs_trace_mask = + + YAFFS_TRACE_SCAN | + YAFFS_TRACE_GC | + YAFFS_TRACE_ERASE | + YAFFS_TRACE_ERROR | + YAFFS_TRACE_TRACING | + YAFFS_TRACE_ALLOCATE | + YAFFS_TRACE_BAD_BLOCKS | + YAFFS_TRACE_VERIFY | + + 0; + + + +// Configuration + +#include "yaffs_flashif2.h" +#include "yaffs_m18_drv.h" + +int yaffs_start_up(void) +{ + static int start_up_called = 0; + + if(start_up_called) + return 0; + start_up_called = 1; + + // Stuff to configure YAFFS + // Stuff to initialise anything special (eg lock semaphore). + yaffsfs_OSInitialisation(); + + + yaffs_m18_install_drv("M18-1"); + + // /yaffs2 yaffs2 file emulation + yflash2_install_drv("yaffs2"); + + return 0; +} + + + diff --git a/direct/basic-test/yaffsnewcfg.c b/direct/test-framework/yaffsnewcfg.c similarity index 100% rename from direct/basic-test/yaffsnewcfg.c rename to direct/test-framework/yaffsnewcfg.c diff --git a/direct/basic-test/ynorsim.c b/direct/test-framework/ynorsim.c similarity index 100% rename from direct/basic-test/ynorsim.c rename to direct/test-framework/ynorsim.c diff --git a/direct/basic-test/ynorsim.h b/direct/test-framework/ynorsim.h similarity index 100% rename from direct/basic-test/ynorsim.h rename to direct/test-framework/ynorsim.h diff --git a/direct/basic-test/yramsim.c b/direct/test-framework/yramsim.c similarity index 100% rename from direct/basic-test/yramsim.c rename to direct/test-framework/yramsim.c diff --git a/direct/basic-test/yramsim.h b/direct/test-framework/yramsim.h similarity index 100% rename from direct/basic-test/yramsim.h rename to direct/test-framework/yramsim.h diff --git a/direct/timothy_tests/quick_tests/quick_tests.h b/direct/timothy_tests/quick_tests/quick_tests.h index ed0d336..9967563 100644 --- a/direct/timothy_tests/quick_tests/quick_tests.h +++ b/direct/timothy_tests/quick_tests/quick_tests.h @@ -329,7 +329,7 @@ test_template test_list[]={ {test_yaffs_write,test_yaffs_write_clean,"test_yaffs_write"}, {test_yaffs_write_EBADF,test_yaffs_write_EBADF_clean,"test_yaffs_write_EBADF"}, - {test_yaffs_write_big_file,test_yaffs_write_big_file_clean,"test_yaffs_write_big_file"}, +// {test_yaffs_write_big_file,test_yaffs_write_big_file_clean,"test_yaffs_write_big_file"}, {test_yaffs_write_EROFS,test_yaffs_write_EROFS_clean,"test_yaffs_write_EROFS"}, {test_yaffs_read,test_yaffs_read_clean,"test_yaffs_read"}, diff --git a/direct/yaffs_osglue.h b/direct/yaffs_osglue.h index bb008f9..7fe0bf4 100644 --- a/direct/yaffs_osglue.h +++ b/direct/yaffs_osglue.h @@ -35,6 +35,8 @@ void yaffsfs_SetError(int err); void *yaffsfs_malloc(size_t size); void yaffsfs_free(void *ptr); +int yaffsfs_CheckMemRegion(const void *addr, size_t size, int writeable); + void yaffsfs_OSInitialisation(void); diff --git a/direct/yaffsfs.c b/direct/yaffsfs.c index 705106e..7ee486a 100644 --- a/direct/yaffsfs.c +++ b/direct/yaffsfs.c @@ -501,6 +501,9 @@ static struct yaffs_dev *yaffsfs_FindDevice(const YCHAR *path, thisMatchLength = 0; matching = 1; + if(!p) + continue; + while (matching && *p && *leftOver) { /* Skip over any /s */ while (yaffsfs_IsPathDivider(*p)) @@ -793,7 +796,7 @@ int yaffs_open_sharing(const YCHAR *path, int oflag, int mode, int sharing) int notDir = 0; int loop = 0; - if (!path) { + if (yaffsfs_CheckMemRegion(path, 0, 0)< 0) { yaffsfs_SetError(-EFAULT); return -1; } @@ -1077,7 +1080,7 @@ static int yaffsfs_do_read(int handle, void *vbuf, unsigned int nbyte, Y_LOFF_T maxRead; u8 *buf = (u8 *) vbuf; - if (!vbuf) { + if (yaffsfs_CheckMemRegion(vbuf, nbyte, 1) < 0) { yaffsfs_SetError(-EFAULT); return -1; } @@ -1199,7 +1202,7 @@ static int yaffsfs_do_write(int handle, const void *vbuf, unsigned int nbyte, int nToWrite = 0; const u8 *buf = (const u8 *)vbuf; - if (!vbuf) { + if (yaffsfs_CheckMemRegion(vbuf, nbyte, 0) < 0) { yaffsfs_SetError(-EFAULT); return -1; } @@ -1310,7 +1313,7 @@ int yaffs_truncate(const YCHAR *path, Y_LOFF_T new_size) int notDir = 0; int loop = 0; - if (!path) { + if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) { yaffsfs_SetError(-EFAULT); return -1; } @@ -1425,7 +1428,7 @@ static int yaffsfs_DoUnlink(const YCHAR *path, int isDirectory) int notDir = 0; int loop = 0; - if (!path) { + if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) { yaffsfs_SetError(-EFAULT); return -1; } @@ -1494,7 +1497,8 @@ int yaffs_rename(const YCHAR *oldPath, const YCHAR *newPath) YCHAR *alt_newpath = NULL; - if (!oldPath || !newPath) { + if (yaffsfs_CheckMemRegion(oldPath, 0, 0) < 0 || + yaffsfs_CheckMemRegion(newPath, 0, 0) < 0) { yaffsfs_SetError(-EFAULT); return -1; } @@ -1633,7 +1637,8 @@ static int yaffsfs_DoStatOrLStat(const YCHAR *path, int notDir = 0; int loop = 0; - if (!path || !buf) { + if (yaffsfs_CheckMemRegion(path, 0, 0) < 0 || + yaffsfs_CheckMemRegion(buf, sizeof(*buf), 1) < 0) { yaffsfs_SetError(-EFAULT); return -1; } @@ -1681,7 +1686,7 @@ int yaffs_fstat(int fd, struct yaffs_stat *buf) int retVal = -1; - if (!buf) { + if (yaffsfs_CheckMemRegion(buf, sizeof(*buf), 1) < 0) { yaffsfs_SetError(-EFAULT); return -1; } @@ -1802,7 +1807,9 @@ static int yaffs_do_setxattr(const YCHAR *path, const char *name, int retVal = -1; - if (!path || !name || !data) { + if (yaffsfs_CheckMemRegion(path, 0, 0) < 0 || + yaffsfs_CheckMemRegion(name, 0, 0) < 0 || + yaffsfs_CheckMemRegion(data, size, 0) < 0) { yaffsfs_SetError(-EFAULT); return -1; } @@ -1858,7 +1865,8 @@ int yaffs_fsetxattr(int fd, const char *name, int retVal = -1; - if (!name || !data) { + if (yaffsfs_CheckMemRegion(name, 0, 0) < 0 || + yaffsfs_CheckMemRegion(data, size, 0) < 0) { yaffsfs_SetError(-EFAULT); return -1; } @@ -1890,7 +1898,9 @@ static int yaffs_do_getxattr(const YCHAR *path, const char *name, int notDir = 0; int loop = 0; - if (!path || !name || !data) { + if (yaffsfs_CheckMemRegion(path, 0, 0) < 0 || + yaffsfs_CheckMemRegion(name, 0, 0) < 0 || + yaffsfs_CheckMemRegion(data, size, 1) < 0) { yaffsfs_SetError(-EFAULT); return -1; } @@ -1942,7 +1952,8 @@ int yaffs_fgetxattr(int fd, const char *name, void *data, int size) int retVal = -1; - if (!name || !data) { + if (yaffsfs_CheckMemRegion(name, 0, 0) < 0 || + yaffsfs_CheckMemRegion(data, size, 1) < 0) { yaffsfs_SetError(-EFAULT); return -1; } @@ -1974,7 +1985,8 @@ static int yaffs_do_listxattr(const YCHAR *path, char *data, int notDir = 0; int loop = 0; - if (!path || !data) { + if (yaffsfs_CheckMemRegion(path, 0, 0) < 0 || + yaffsfs_CheckMemRegion(data, size, 1) < 0) { yaffsfs_SetError(-EFAULT); return -1; } @@ -2027,7 +2039,7 @@ int yaffs_flistxattr(int fd, char *data, int size) int retVal = -1; - if (!data) { + if (yaffsfs_CheckMemRegion(data, size, 1) < 0) { yaffsfs_SetError(-EFAULT); return -1; } @@ -2059,7 +2071,8 @@ static int yaffs_do_removexattr(const YCHAR *path, const char *name, int loop = 0; int retVal = -1; - if (!path || !name) { + if (yaffsfs_CheckMemRegion(path, 0, 0) < 0 || + yaffsfs_CheckMemRegion(name, 0, 0) < 0) { yaffsfs_SetError(-EFAULT); return -1; } @@ -2112,7 +2125,7 @@ int yaffs_fremovexattr(int fd, const char *name) int retVal = -1; - if (!name) { + if (yaffsfs_CheckMemRegion(name, 0, 0) < 0) { yaffsfs_SetError(-EFAULT); return -1; } @@ -2236,7 +2249,7 @@ int yaffs_access(const YCHAR *path, int amode) int loop = 0; int retval = -1; - if (!path) { + if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) { yaffsfs_SetError(-EFAULT); return -1; } @@ -2294,7 +2307,7 @@ int yaffs_chmod(const YCHAR *path, mode_t mode) int notDir = 0; int loop = 0; - if (!path) { + if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) { yaffsfs_SetError(-EFAULT); return -1; } @@ -2366,7 +2379,7 @@ int yaffs_mkdir(const YCHAR *path, mode_t mode) int notDir = 0; int loop = 0; - if (!path) { + if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) { yaffsfs_SetError(-EFAULT); return -1; } @@ -2420,7 +2433,7 @@ int yaffs_rmdir(const YCHAR *path) int result; YCHAR *alt_path; - if (!path) { + if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) { yaffsfs_SetError(-EFAULT); return -1; } @@ -2457,7 +2470,7 @@ int yaffs_mount_common(const YCHAR *path, int read_only, int skip_checkpt) int result = YAFFS_FAIL; struct yaffs_dev *dev = NULL; - if (!path) { + if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) { yaffsfs_SetError(-EFAULT); return -1; } @@ -2516,7 +2529,7 @@ int yaffs_sync(const YCHAR *path) struct yaffs_dev *dev = NULL; YCHAR *dummy; - if (!path) { + if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) { yaffsfs_SetError(-EFAULT); return -1; } @@ -2565,7 +2578,7 @@ int yaffs_remount(const YCHAR *path, int force, int read_only) int retVal = -1; struct yaffs_dev *dev = NULL; - if (!path) { + if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) { yaffsfs_SetError(-EFAULT); return -1; } @@ -2605,7 +2618,7 @@ int yaffs_unmount2(const YCHAR *path, int force) int retVal = -1; struct yaffs_dev *dev = NULL; - if (!path) { + if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) { yaffsfs_SetError(-EFAULT); return -1; } @@ -2715,7 +2728,7 @@ Y_LOFF_T yaffs_freespace(const YCHAR *path) struct yaffs_dev *dev = NULL; YCHAR *dummy; - if (!path) { + if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) { yaffsfs_SetError(-EFAULT); return -1; } @@ -2744,7 +2757,7 @@ Y_LOFF_T yaffs_totalspace(const YCHAR *path) struct yaffs_dev *dev = NULL; YCHAR *dummy; - if (!path) { + if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) { yaffsfs_SetError(-EFAULT); return -1; } @@ -2775,7 +2788,7 @@ int yaffs_inodecount(const YCHAR *path) struct yaffs_dev *dev = NULL; YCHAR *dummy; - if (!path) { + if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) { yaffsfs_SetError(-EFAULT); return -1; } @@ -2927,7 +2940,7 @@ yaffs_DIR *yaffs_opendir(const YCHAR *dirname) int notDir = 0; int loop = 0; - if (!dirname) { + if (yaffsfs_CheckMemRegion(dirname, 0, 0) < 0) { yaffsfs_SetError(-EFAULT); return NULL; } @@ -3021,6 +3034,9 @@ void yaffs_rewinddir(yaffs_DIR *dirp) dsc = (struct yaffsfs_DirSearchContxt *) dirp; + if (yaffsfs_CheckMemRegion(dirp, sizeof(*dsc), 0) < 0) + return; + yaffsfs_Lock(); yaffsfs_SetDirRewound(dsc); @@ -3034,7 +3050,7 @@ int yaffs_closedir(yaffs_DIR *dirp) dsc = (struct yaffsfs_DirSearchContxt *) dirp; - if (!dsc) { + if (yaffsfs_CheckMemRegion(dirp, sizeof(*dsc), 0) < 0) { yaffsfs_SetError(-EFAULT); return -1; } @@ -3058,7 +3074,8 @@ int yaffs_symlink(const YCHAR *oldpath, const YCHAR *newpath) int notDir = 0; int loop = 0; - if (!oldpath || !newpath) { + if (yaffsfs_CheckMemRegion(oldpath, 0, 0) < 0 || + yaffsfs_CheckMemRegion(newpath, 0, 0) < 0) { yaffsfs_SetError(-EFAULT); return -1; } @@ -3105,7 +3122,8 @@ int yaffs_readlink(const YCHAR *path, YCHAR *buf, int bufsiz) int notDir = 0; int loop = 0; - if (!path || !buf) { + if (yaffsfs_CheckMemRegion(path, 0, 0) < 0 || + yaffsfs_CheckMemRegion(buf, bufsiz, 1) < 0) { yaffsfs_SetError(-EFAULT); return -1; } @@ -3146,7 +3164,8 @@ int yaffs_link(const YCHAR *oldpath, const YCHAR *linkpath) int lnkLoop = 0; YCHAR *newname; - if (!oldpath || !linkpath) { + if (yaffsfs_CheckMemRegion(oldpath, 0, 0) < 0 || + yaffsfs_CheckMemRegion(linkpath, 0, 0) < 0) { yaffsfs_SetError(-EFAULT); return -1; } @@ -3218,7 +3237,7 @@ int yaffs_n_handles(const YCHAR *path) { struct yaffs_obj *obj; - if (!path) { + if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) { yaffsfs_SetError(-EFAULT); return -1; } diff --git a/yaffs_checkptrw.c b/yaffs_checkptrw.c index 8478eb8..e739fb4 100644 --- a/yaffs_checkptrw.c +++ b/yaffs_checkptrw.c @@ -74,7 +74,7 @@ static int yaffs_checkpt_erase(struct yaffs_dev *dev) { int i; - if (!dev->param.erase_fn) + if (!dev->drv.drv_erase_fn) return 0; yaffs_trace(YAFFS_TRACE_CHECKPOINT, "checking blocks %d to %d", @@ -91,14 +91,14 @@ static int yaffs_checkpt_erase(struct yaffs_dev *dev) dev->n_erasures++; - result = dev->param.erase_fn(dev, offset_i); + result = dev->drv.drv_erase_fn(dev, offset_i); if(result) { bi->block_state = YAFFS_BLOCK_STATE_EMPTY; dev->n_erased_blocks++; dev->n_free_chunks += dev->param.chunks_per_block; } else { - dev->param.bad_block_fn(dev, offset_i); + dev->drv.drv_mark_bad_fn(dev, offset_i); bi->block_state = YAFFS_BLOCK_STATE_DEAD; } } @@ -159,7 +159,7 @@ static void yaffs2_checkpt_find_block(struct yaffs_dev *dev) enum yaffs_block_state state; u32 seq; - dev->param.read_chunk_tags_fn(dev, + dev->tagger.read_chunk_tags_fn(dev, apply_chunk_offset(dev, chunk), NULL, &tags); yaffs_trace(YAFFS_TRACE_CHECKPOINT, @@ -171,7 +171,7 @@ static void yaffs2_checkpt_find_block(struct yaffs_dev *dev) if (tags.seq_number != YAFFS_SEQUENCE_CHECKPOINT_DATA) continue; - dev->param.query_block_fn(dev, + dev->tagger.query_block_fn(dev, apply_block_offset(dev, i), &state, &seq); if (state == YAFFS_BLOCK_STATE_DEAD) @@ -200,9 +200,10 @@ int yaffs2_checkpt_open(struct yaffs_dev *dev, int writing) dev->checkpt_open_write = writing; /* Got the functions we need? */ - if (!dev->param.write_chunk_tags_fn || - !dev->param.read_chunk_tags_fn || - !dev->param.erase_fn || !dev->param.bad_block_fn) + if (!dev->tagger.write_chunk_tags_fn || + !dev->tagger.read_chunk_tags_fn || + !dev->drv.drv_erase_fn || + !dev->drv.drv_mark_bad_fn) return 0; if (writing && !yaffs2_checkpt_space_ok(dev)) @@ -298,7 +299,7 @@ static int yaffs2_checkpt_flush_buffer(struct yaffs_dev *dev) dev->n_page_writes++; - dev->param.write_chunk_tags_fn(dev, offset_chunk, + dev->tagger.write_chunk_tags_fn(dev, offset_chunk, dev->checkpt_buffer, &tags); dev->checkpt_page_seq++; dev->checkpt_cur_chunk++; @@ -382,7 +383,7 @@ int yaffs2_checkpt_rd(struct yaffs_dev *dev, void *data, int n_bytes) dev->n_page_reads++; /* read in the next chunk */ - dev->param.read_chunk_tags_fn(dev, + dev->tagger.read_chunk_tags_fn(dev, offset_chunk, dev->checkpt_buffer, &tags); diff --git a/yaffs_guts.c b/yaffs_guts.c index 9c296e2..9f6b409 100644 --- a/yaffs_guts.c +++ b/yaffs_guts.c @@ -17,6 +17,7 @@ #include "yaffs_guts.h" #include "yaffs_getblockinfo.h" #include "yaffs_tagscompat.h" +#include "yaffs_tagsmarshall.h" #include "yaffs_nand.h" #include "yaffs_yaffs1.h" #include "yaffs_yaffs2.h" @@ -609,10 +610,10 @@ static void yaffs_retire_block(struct yaffs_dev *dev, int flash_block) memset(buffer, 0xff, dev->data_bytes_per_chunk); memset(&tags, 0, sizeof(tags)); tags.seq_number = YAFFS_SEQUENCE_BAD_BLOCK; - if (dev->param.write_chunk_tags_fn(dev, chunk_id - - dev->chunk_offset, - buffer, - &tags) != YAFFS_OK) + if (dev->tagger.write_chunk_tags_fn(dev, chunk_id - + dev->chunk_offset, + buffer, + &tags) != YAFFS_OK) yaffs_trace(YAFFS_TRACE_ALWAYS, "yaffs: Failed to write bad block marker to block %d", flash_block); @@ -2804,7 +2805,8 @@ static int yaffs_check_gc(struct yaffs_dev *dev, int background) int erased_chunks; int checkpt_block_adjust; - if (dev->param.gc_control && (dev->param.gc_control(dev) & 1) == 0) + if (dev->param.gc_control_fn && + (dev->param.gc_control_fn(dev) & 1) == 0) return YAFFS_OK; if (dev->gc_disable) @@ -3566,9 +3568,11 @@ int yaffs_do_file_wr(struct yaffs_obj *in, const u8 *buffer, loff_t offset, } if (n_copy != dev->data_bytes_per_chunk || + !dev->param.cache_bypass_aligned || dev->param.inband_tags) { /* An incomplete start or end chunk (or maybe both * start and end chunk), or we're using inband tags, + * or we're forcing writes through the cache, * so we want to use the cache buffers. */ if (dev->param.n_caches > 0) { @@ -4536,30 +4540,33 @@ YCHAR *yaffs_get_symlink_alias(struct yaffs_obj *obj) /*--------------------------- Initialisation code -------------------------- */ -static int yaffs_check_dev_fns(const struct yaffs_dev *dev) +static int yaffs_check_dev_fns(struct yaffs_dev *dev) { + struct yaffs_driver *drv = &dev->drv; + struct yaffs_tags_handler *tagger = &dev->tagger; + /* Common functions, gotta have */ - if (!dev->param.erase_fn || !dev->param.initialise_flash_fn) + if (!drv->drv_read_chunk_fn || + !drv->drv_write_chunk_fn || + !drv->drv_erase_fn) return 0; - /* Can use the "with tags" style interface for yaffs1 or yaffs2 */ - if (dev->param.write_chunk_tags_fn && - dev->param.read_chunk_tags_fn && - !dev->param.write_chunk_fn && - !dev->param.read_chunk_fn && - dev->param.bad_block_fn && dev->param.query_block_fn) - return 1; + if (dev->param.is_yaffs2 && + (!drv->drv_mark_bad_fn || !drv->drv_check_bad_fn)) + return 0; - /* Can use the "spare" style interface for yaffs1 */ - if (!dev->param.is_yaffs2 && - !dev->param.write_chunk_tags_fn && - !dev->param.read_chunk_tags_fn && - dev->param.write_chunk_fn && - dev->param.read_chunk_fn && - !dev->param.bad_block_fn && !dev->param.query_block_fn) - return 1; + /* Install the default tags marshalling functions if needed. */ + yaffs_tags_compat_install(dev); + yaffs_tags_marshall_install(dev); - return 0; /* bad */ + /* Check we now have the marshalling functions required. */ + if (!tagger->write_chunk_tags_fn || + !tagger->read_chunk_tags_fn || + !tagger->query_block_fn || + !tagger->mark_bad_fn) + return 0; + + return 1; } static int yaffs_create_initial_dir(struct yaffs_dev *dev) @@ -4929,8 +4936,7 @@ void yaffs_deinitialise(struct yaffs_dev *dev) dev->is_mounted = 0; - if (dev->param.deinitialise_flash_fn) - dev->param.deinitialise_flash_fn(dev); + yaffs_deinit_nand(dev); } } diff --git a/yaffs_guts.h b/yaffs_guts.h index 0e334bd..26ad54d 100644 --- a/yaffs_guts.h +++ b/yaffs_guts.h @@ -520,7 +520,7 @@ struct yaffs_param { /* * Entry parameters set up way early. Yaffs sets up the rest. * The structure should be zeroed out before use so that unused - * and defualt values are zero. + * and default values are zero. */ int inband_tags; /* Use unband tags */ @@ -536,6 +536,10 @@ struct yaffs_param { int n_caches; /* If <= 0, then short op caching is disabled, * else the number of short op caches. */ + int cache_bypass_aligned; /* If non-zero then bypass the cache for + * aligned writes. + */ + int use_nand_ecc; /* Flag to decide whether or not to use * NAND driver ECC on data (yaffs1) */ int tags_9bytes; /* Use 9 byte tags */ @@ -554,29 +558,10 @@ struct yaffs_param { int enable_xattr; /* Enable xattribs */ - /* NAND access functions (Must be set before calling YAFFS) */ - - int (*write_chunk_fn) (struct yaffs_dev *dev, - int nand_chunk, const u8 *data, - const struct yaffs_spare *spare); - int (*read_chunk_fn) (struct yaffs_dev *dev, - int nand_chunk, u8 *data, - struct yaffs_spare *spare); - int (*erase_fn) (struct yaffs_dev *dev, int flash_block); - int (*initialise_flash_fn) (struct yaffs_dev *dev); - int (*deinitialise_flash_fn) (struct yaffs_dev *dev); - - /* yaffs2 mode functions */ - int (*write_chunk_tags_fn) (struct yaffs_dev *dev, - int nand_chunk, const u8 *data, - const struct yaffs_ext_tags *tags); - int (*read_chunk_tags_fn) (struct yaffs_dev *dev, - int nand_chunk, u8 *data, - struct yaffs_ext_tags *tags); - int (*bad_block_fn) (struct yaffs_dev *dev, int block_no); - int (*query_block_fn) (struct yaffs_dev *dev, int block_no, - enum yaffs_block_state *state, - u32 *seq_number); + int max_objects; /* + * Set to limit the number of objects created. + * 0 = no limit. + */ /* The remove_obj_fn function must be supplied by OS flavours that * need it. @@ -589,7 +574,7 @@ struct yaffs_param { void (*sb_dirty_fn) (struct yaffs_dev *dev); /* Callback to control garbage collection. */ - unsigned (*gc_control) (struct yaffs_dev *dev); + unsigned (*gc_control_fn) (struct yaffs_dev *dev); /* Debug control flags. Don't use unless you know what you're doing */ int use_header_file_size; /* Flag to determine if we should use @@ -608,14 +593,41 @@ struct yaffs_param { int disable_summary; - int max_objects; /* - * Set to limit the number of objects created. - * 0 = no limit. - */ +}; + +struct yaffs_driver { + int (*drv_write_chunk_fn) (struct yaffs_dev *dev, int nand_chunk, + const u8 *data, int data_len, + const u8 *oob, int oob_len); + int (*drv_read_chunk_fn) (struct yaffs_dev *dev, int nand_chunk, + u8 *data, int data_len, + u8 *oob, int oob_len, + enum yaffs_ecc_result *ecc_result); + int (*drv_erase_fn) (struct yaffs_dev *dev, int block_no); + int (*drv_mark_bad_fn) (struct yaffs_dev *dev, int block_no); + int (*drv_check_bad_fn) (struct yaffs_dev *dev, int block_no); + int (*drv_initialise_fn) (struct yaffs_dev *dev); + int (*drv_deinitialise_fn) (struct yaffs_dev *dev); +}; + +struct yaffs_tags_handler { + int (*write_chunk_tags_fn) (struct yaffs_dev *dev, + int nand_chunk, const u8 *data, + const struct yaffs_ext_tags *tags); + int (*read_chunk_tags_fn) (struct yaffs_dev *dev, + int nand_chunk, u8 *data, + struct yaffs_ext_tags *tags); + + int (*query_block_fn) (struct yaffs_dev *dev, int block_no, + enum yaffs_block_state *state, + u32 *seq_number); + int (*mark_bad_fn) (struct yaffs_dev *dev, int block_no); }; struct yaffs_dev { struct yaffs_param param; + struct yaffs_driver drv; + struct yaffs_tags_handler tagger; /* Context storage. Holds extra OS specific data for this device */ @@ -762,6 +774,7 @@ struct yaffs_dev { u32 n_page_writes; u32 n_page_reads; u32 n_erasures; + u32 n_bad_markings; u32 n_erase_failures; u32 n_gc_copies; u32 all_gcs; diff --git a/yaffs_linux.h b/yaffs_linux.h index 8c522c8..c541e31 100644 --- a/yaffs_linux.h +++ b/yaffs_linux.h @@ -29,8 +29,6 @@ struct yaffs_linux_context { * at compile time so we have to allocate it. */ struct list_head search_contexts; - void (*put_super_fn) (struct super_block *sb); - struct task_struct *readdir_process; unsigned mount_id; }; diff --git a/yaffs_mtdif.c b/yaffs_mtdif.c deleted file mode 100644 index edc1525..0000000 --- a/yaffs_mtdif.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. - * - * Copyright (C) 2002-2011 Aleph One Ltd. - * for Toby Churchill Ltd and Brightstar Engineering - * - * Created by Charles Manning - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include "yportenv.h" - -#include "yaffs_mtdif.h" - -#include "linux/mtd/mtd.h" -#include "linux/types.h" -#include "linux/time.h" -#include "linux/mtd/nand.h" - -#include "yaffs_linux.h" - -int nandmtd_erase_block(struct yaffs_dev *dev, int block_no) -{ - struct mtd_info *mtd = yaffs_dev_to_mtd(dev); - u32 addr = - ((loff_t) block_no) * dev->param.total_bytes_per_chunk * - dev->param.chunks_per_block; - struct erase_info ei; - int retval = 0; - - ei.mtd = mtd; - ei.addr = addr; - ei.len = dev->param.total_bytes_per_chunk * dev->param.chunks_per_block; - ei.time = 1000; - ei.retries = 2; - ei.callback = NULL; - ei.priv = (u_long) dev; - - retval = mtd->erase(mtd, &ei); - - if (retval == 0) - return YAFFS_OK; - - return YAFFS_FAIL; -} - -int nandmtd_initialise(struct yaffs_dev *dev) -{ - return YAFFS_OK; -} diff --git a/yaffs_mtdif.h b/yaffs_mtdif.h index 3ef5581..e5172eb 100644 --- a/yaffs_mtdif.h +++ b/yaffs_mtdif.h @@ -18,6 +18,6 @@ #include "yaffs_guts.h" -int nandmtd_erase_block(struct yaffs_dev *dev, int block_no); -int nandmtd_initialise(struct yaffs_dev *dev); +void yaffs_mtd_drv_install(struct yaffs_dev *dev); + #endif diff --git a/yaffs_mtdif1.h b/yaffs_mtdif1.h deleted file mode 100644 index 6a5df50..0000000 --- a/yaffs_mtdif1.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * YAFFS: Yet another Flash File System. A NAND-flash specific file system. - * - * Copyright (C) 2002-2011 Aleph One Ltd. - * for Toby Churchill Ltd and Brightstar Engineering - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 as - * published by the Free Software Foundation. - * - * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. - */ - -#ifndef __YAFFS_MTDIF1_H__ -#define __YAFFS_MTDIF1_H__ - -int nandmtd1_write_chunk_tags(struct yaffs_dev *dev, int nand_chunk, - const u8 *data, - const struct yaffs_ext_tags *tags); - -int nandmtd1_read_chunk_tags(struct yaffs_dev *dev, int nand_chunk, - u8 *data, struct yaffs_ext_tags *tags); - -int nandmtd1_mark_block_bad(struct yaffs_dev *dev, int block_no); - -int nandmtd1_query_block(struct yaffs_dev *dev, int block_no, - enum yaffs_block_state *state, u32 *seq_number); - -#endif diff --git a/yaffs_mtdif1_multi.c b/yaffs_mtdif1_multi.c deleted file mode 100644 index 14d5c6f..0000000 --- a/yaffs_mtdif1_multi.c +++ /dev/null @@ -1,364 +0,0 @@ -/* - * YAFFS: Yet another FFS. A NAND-flash specific file system. - * - * Copyright (C) 2002-2011 Aleph One Ltd. - * for Toby Churchill Ltd and Brightstar Engineering - * - * Created by Charles Manning - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -/* - * This module provides the interface between yaffs_nand.c and the - * MTD API. This version is used when the MTD interface supports the - * 'mtd_oob_ops' style calls to read_oob and write_oob, circa 2.6.17, - * and we have small-page NAND device. - * - * These functions are invoked via function pointers in yaffs_nand.c. - * This replaces functionality provided by functions in yaffs_mtdif.c - * and the yaffs_tags compatability functions in yaffs_tagscompat.c that are - * called in yaffs_mtdif.c when the function pointers are NULL. - * We assume the MTD layer is performing ECC (use_nand_ecc is true). - */ - -#include "yportenv.h" -#include "yaffs_trace.h" -#include "yaffs_guts.h" -#include "yaffs_packedtags1.h" -#include "yaffs_tagscompat.h" /* for yaffs_calc_tags_ecc */ -#include "yaffs_linux.h" - -#include "linux/kernel.h" -#include "linux/version.h" -#include "linux/types.h" -#include "linux/mtd/mtd.h" - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) -#define MTD_OPS_AUTO_OOB MTD_OOB_AUTO -#endif - - -/* Don't compile this module if we don't have MTD's mtd_oob_ops interface */ -#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17)) - - -#if 0 -/* Use the following nand_ecclayout with MTD when using - * 9 byte tags and the older on-NAND tags layout. - * If you have existing Yaffs images and the byte order differs from this, - * adjust 'oobfree' to match your existing Yaffs data. - * - * This nand_ecclayout scatters/gathers to/from the old-yaffs layout with the - * page_status byte (at NAND spare offset 4) scattered/gathered from/to - * the 9th byte. - * - * Old-style on-NAND format: T0,T1,T2,T3,P,B,T4,T5,E0,E1,E2,T6,T7,E3,E4,E5 - * We have/need packed_tags1 plus page_status: T0,T1,T2,T3,T4,T5,T6,T7,P - * where Tn are the tag bytes, En are MTD's ECC bytes, P is the page_status - * byte and B is the small-page bad-block indicator byte. - */ -static struct nand_ecclayout nand_oob_16 = { - .eccbytes = 6, - .eccpos = {8, 9, 10, 13, 14, 15}, - .oobavail = 9, - .oobfree = {{0, 4}, {6, 2}, {11, 2}, {4, 1} } -}; -#endif - -/* Write a chunk (page) of data to NAND. - * - * Caller always provides ExtendedTags data which are converted to a more - * compact (packed) form for storage in NAND. A mini-ECC runs over the - * contents of the tags meta-data; used to valid the tags when read. - * - * - Pack ExtendedTags to packed_tags1 form - * - Compute mini-ECC for packed_tags1 - * - Write data and packed tags to NAND. - * - * Note: Due to the use of the packed_tags1 meta-data which does not include - * a full sequence number (as found in the larger packed_tags2 form) it is - * necessary for Yaffs to re-write a chunk/page (just once) to mark it as - * discarded and dirty. This is not ideal: newer NAND parts are supposed - * to be written just once. When Yaffs performs this operation, this - * function is called with a NULL data pointer -- calling MTD write_oob - * without data is valid usage (2.6.17). - * - * Any underlying MTD error results in YAFFS_FAIL. - * Returns YAFFS_OK or YAFFS_FAIL. - */ -int nandmtd1_write_chunk_tags(struct yaffs_dev *dev, - int nand_chunk, const u8 *data, - const struct yaffs_ext_tags *etags) -{ - struct mtd_info *mtd = yaffs_dev_to_mtd(dev); - int chunk_bytes = dev->data_bytes_per_chunk; - loff_t addr = ((loff_t) nand_chunk) * chunk_bytes; - struct mtd_oob_ops ops; - struct yaffs_packed_tags1 pt1; - int retval; - - /* we assume that packed_tags1 and struct yaffs_tags are compatible */ - compile_time_assertion(sizeof(struct yaffs_packed_tags1) == 12); - compile_time_assertion(sizeof(struct yaffs_tags) == 8); - - yaffs_pack_tags1(&pt1, etags); - yaffs_calc_tags_ecc((struct yaffs_tags *)&pt1); - - /* When deleting a chunk, the upper layer provides only skeletal - * etags, one with is_deleted set. However, we need to update the - * tags, not erase them completely. So we use the NAND write property - * that only zeroed-bits stick and set tag bytes to all-ones and - * zero just the (not) deleted bit. - */ - if(dev->param.tags_9bytes) { - ((u8 *) &pt1)[8] = 0xff; - if (etags->is_deleted) { - memset(&pt1, 0xff, 8); - /* zero page_status byte to indicate deleted */ - ((u8 *) &pt1)[8] = 0; - } - } else { - if (etags->is_deleted) { - memset(&pt1, 0xff, 8); - /* clear delete status bit to indicate deleted */ - pt1.deleted = 0; - } - } - - memset(&ops, 0, sizeof(ops)); - ops.mode = MTD_OPS_AUTO_OOB; - ops.len = (data) ? chunk_bytes : 0; - ops.ooblen = dev->param.tags_9bytes ? 9 : 8; - ops.datbuf = (u8 *) data; - ops.oobbuf = (u8 *) &pt1; - - retval = mtd->write_oob(mtd, addr, &ops); - if (retval) { - yaffs_trace(YAFFS_TRACE_MTD, - "write_oob failed, chunk %d, mtd error %d", - nand_chunk, retval); - } - return retval ? YAFFS_FAIL : YAFFS_OK; -} - -/* Return with empty ExtendedTags but add ecc_result. - */ -static int rettags(struct yaffs_ext_tags *etags, int ecc_result, int retval) -{ - if (etags) { - memset(etags, 0, sizeof(*etags)); - etags->ecc_result = ecc_result; - } - return retval; -} - -/* Read a chunk (page) from NAND. - * - * Caller expects ExtendedTags data to be usable even on error; that is, - * all members except ecc_result and block_bad are zeroed. - * - * - Check ECC results for data (if applicable) - * - Check for blank/erased block (return empty ExtendedTags if blank) - * - Check the packed_tags1 mini-ECC (correct if necessary/possible) - * - Convert packed_tags1 to ExtendedTags - * - Update ecc_result and block_bad members to refect state. - * - * Returns YAFFS_OK or YAFFS_FAIL. - */ -int nandmtd1_read_chunk_tags(struct yaffs_dev *dev, - int nand_chunk, u8 *data, - struct yaffs_ext_tags *etags) -{ - struct mtd_info *mtd = yaffs_dev_to_mtd(dev); - int chunk_bytes = dev->data_bytes_per_chunk; - loff_t addr = ((loff_t) nand_chunk) * chunk_bytes; - int eccres = YAFFS_ECC_RESULT_NO_ERROR; - struct mtd_oob_ops ops; - struct yaffs_packed_tags1 pt1; - int retval; - int deleted; - - memset(&ops, 0, sizeof(ops)); - ops.mode = MTD_OPS_AUTO_OOB; - ops.len = (data) ? chunk_bytes : 0; - ops.ooblen = dev->param.tags_9bytes ? 9 : 8; - ops.datbuf = data; - ops.oobbuf = (u8 *) &pt1; - -#if (MTD_VERSION_CODE < MTD_VERSION(2, 6, 20)) - /* In MTD 2.6.18 to 2.6.19 nand_base.c:nand_do_read_oob() has a bug; - * help it out with ops.len = ops.ooblen when ops.datbuf == NULL. - */ - ops.len = (ops.datbuf) ? ops.len : ops.ooblen; -#endif - /* Read page and oob using MTD. - * Check status and determine ECC result. - */ - retval = mtd->read_oob(mtd, addr, &ops); - if (retval) - yaffs_trace(YAFFS_TRACE_MTD, - "read_oob failed, chunk %d, mtd error %d", - nand_chunk, retval); - - switch (retval) { - case 0: - /* no error */ - break; - - case -EUCLEAN: - /* MTD's ECC fixed the data */ - eccres = YAFFS_ECC_RESULT_FIXED; - dev->n_ecc_fixed++; - break; - - case -EBADMSG: - /* MTD's ECC could not fix the data */ - dev->n_ecc_unfixed++; - /* fall into... */ - default: - rettags(etags, YAFFS_ECC_RESULT_UNFIXED, 0); - etags->block_bad = (mtd->block_isbad) (mtd, addr); - return YAFFS_FAIL; - } - - /* Check for a blank/erased chunk. - */ - if (yaffs_check_ff((u8 *) &pt1, 8)) { - /* when blank, upper layers want ecc_result to be <= NO_ERROR */ - return rettags(etags, YAFFS_ECC_RESULT_NO_ERROR, YAFFS_OK); - } - - if(dev->param.tags_9bytes) { - deleted = (hweight8(((u8 *) &pt1)[8]) < 7); - } else { - /* Read deleted status (bit) then return it to it's non-deleted - * state before performing tags mini-ECC check. pt1.deleted is - * inverted. - */ - deleted = !pt1.deleted; - pt1.deleted = 1; - } - - /* Check the packed tags mini-ECC and correct if necessary/possible. - */ - retval = yaffs_check_tags_ecc((struct yaffs_tags *)&pt1); - switch (retval) { - case 0: - /* no tags error, use MTD result */ - break; - case 1: - /* recovered tags-ECC error */ - dev->n_tags_ecc_fixed++; - if (eccres == YAFFS_ECC_RESULT_NO_ERROR) - eccres = YAFFS_ECC_RESULT_FIXED; - break; - default: - /* unrecovered tags-ECC error */ - dev->n_tags_ecc_unfixed++; - return rettags(etags, YAFFS_ECC_RESULT_UNFIXED, YAFFS_FAIL); - } - - /* Unpack the tags to extended form and set ECC result. - * [set should_be_ff just to keep yaffs_unpack_tags1 happy] - */ - pt1.should_be_ff = 0xffffffff; - yaffs_unpack_tags1(etags, &pt1); - etags->ecc_result = eccres; - - /* Set deleted state */ - etags->is_deleted = deleted; - return YAFFS_OK; -} - -/* Mark a block bad. - * - * This is a persistant state. - * Use of this function should be rare. - * - * Returns YAFFS_OK or YAFFS_FAIL. - */ -int nandmtd1_mark_block_bad(struct yaffs_dev *dev, int block_no) -{ - struct mtd_info *mtd = yaffs_dev_to_mtd(dev); - int blocksize = dev->param.chunks_per_block * dev->data_bytes_per_chunk; - int retval; - - yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, "marking block %d bad", block_no); - - retval = mtd->block_markbad(mtd, (loff_t) blocksize * block_no); - return (retval) ? YAFFS_FAIL : YAFFS_OK; -} - -/* Check any MTD prerequists. - * - * Returns YAFFS_OK or YAFFS_FAIL. - */ -static int nandmtd1_test_prerequists(struct yaffs_dev *dev, struct mtd_info *mtd) -{ - /* 2.6.18 has mtd->ecclayout->oobavail */ - /* 2.6.21 has mtd->ecclayout->oobavail and mtd->oobavail */ - int oobavail = mtd->ecclayout->oobavail; - - if (oobavail < (dev->param.tags_9bytes ? 9 : 8)) { - yaffs_trace(YAFFS_TRACE_ERROR, - "mtd device has only %d bytes for tags, need %d", - oobavail, dev->param.tags_9bytes ? 9 : 8); - return YAFFS_FAIL; - } - return YAFFS_OK; -} - -/* Query for the current state of a specific block. - * - * Examine the tags of the first chunk of the block and return the state: - * - YAFFS_BLOCK_STATE_DEAD, the block is marked bad - * - YAFFS_BLOCK_STATE_NEEDS_SCAN, the block is in use - * - YAFFS_BLOCK_STATE_EMPTY, the block is clean - * - * Always returns YAFFS_OK. - */ -int nandmtd1_query_block(struct yaffs_dev *dev, int block_no, - enum yaffs_block_state *state_ptr, u32 * seq_ptr) -{ - struct mtd_info *mtd = yaffs_dev_to_mtd(dev); - int chunk_num = block_no * dev->param.chunks_per_block; - loff_t addr = (loff_t) chunk_num * dev->data_bytes_per_chunk; - struct yaffs_ext_tags etags; - int state = YAFFS_BLOCK_STATE_DEAD; - int seqnum = 0; - int retval; - - /* We don't yet have a good place to test for MTD config prerequists. - * Do it here as we are called during the initial scan. - */ - if (nandmtd1_test_prerequists(dev, mtd) != YAFFS_OK) - return YAFFS_FAIL; - - retval = nandmtd1_read_chunk_tags(dev, chunk_num, NULL, &etags); - etags.block_bad = (mtd->block_isbad) (mtd, addr); - if (etags.block_bad) { - yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, - "block %d is marked bad", - block_no); - state = YAFFS_BLOCK_STATE_DEAD; - } else if (etags.ecc_result != YAFFS_ECC_RESULT_NO_ERROR) { - /* bad tags, need to look more closely */ - state = YAFFS_BLOCK_STATE_NEEDS_SCAN; - } else if (etags.chunk_used) { - state = YAFFS_BLOCK_STATE_NEEDS_SCAN; - seqnum = etags.seq_number; - } else { - state = YAFFS_BLOCK_STATE_EMPTY; - } - - *state_ptr = state; - *seq_ptr = seqnum; - - /* query always succeeds */ - return YAFFS_OK; -} - -#endif /*MTD_VERSION */ diff --git a/yaffs_mtdif1_single.c b/yaffs_mtdif1_single.c deleted file mode 100644 index dbc9122..0000000 --- a/yaffs_mtdif1_single.c +++ /dev/null @@ -1,325 +0,0 @@ -/* - * YAFFS: Yet another FFS. A NAND-flash specific file system. - * - * Copyright (C) 2002-2011 Aleph One Ltd. - * for Toby Churchill Ltd and Brightstar Engineering - * - * Created by Charles Manning - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -/* - * This module provides the interface between yaffs_nand.c and the - * MTD API. This version is used when the MTD interface supports the - * 'mtd_oob_ops' style calls to read_oob and write_oob, circa 2.6.17, - * and we have small-page NAND device. - * - * These functions are invoked via function pointers in yaffs_nand.c. - * This replaces functionality provided by functions in yaffs_mtdif.c - * and the yaffs_tags compatability functions in yaffs_tagscompat.c that are - * called in yaffs_mtdif.c when the function pointers are NULL. - * We assume the MTD layer is performing ECC (use_nand_ecc is true). - */ - -#include "yportenv.h" -#include "yaffs_trace.h" -#include "yaffs_guts.h" -#include "yaffs_packedtags1.h" -#include "yaffs_tagscompat.h" /* for yaffs_calc_tags_ecc */ -#include "yaffs_linux.h" -#include "linux/kernel.h" -#include "linux/version.h" -#include "linux/types.h" -#include "linux/mtd/mtd.h" - -/* Write a chunk (page) of data to NAND. - * - * Caller always provides ExtendedTags data which are converted to a more - * compact (packed) form for storage in NAND. A mini-ECC runs over the - * contents of the tags meta-data; used to valid the tags when read. - * - * - Pack ExtendedTags to packed_tags1 form - * - Compute mini-ECC for packed_tags1 - * - Write data and packed tags to NAND. - * - * Note: Due to the use of the packed_tags1 meta-data which does not include - * a full sequence number (as found in the larger packed_tags2 form) it is - * necessary for Yaffs to re-write a chunk/page (just once) to mark it as - * discarded and dirty. This is not ideal: newer NAND parts are supposed - * to be written just once. When Yaffs performs this operation, this - * function is called with a NULL data pointer -- calling MTD write_oob - * without data is valid usage (2.6.17). - * - * Any underlying MTD error results in YAFFS_FAIL. - * Returns YAFFS_OK or YAFFS_FAIL. - */ -int nandmtd1_write_chunk_tags(struct yaffs_dev *dev, - int nand_chunk, const u8 *data, - const struct yaffs_ext_tags *etags) -{ - struct mtd_info *mtd = yaffs_dev_to_mtd(dev); - int chunk_bytes = dev->data_bytes_per_chunk; - loff_t addr = ((loff_t) nand_chunk) * chunk_bytes; - struct mtd_oob_ops ops; - struct yaffs_packed_tags1 pt1; - int retval; - - /* we assume that packed_tags1 and struct yaffs_tags are compatible */ - compile_time_assertion(sizeof(struct yaffs_packed_tags1) == 12); - compile_time_assertion(sizeof(struct yaffs_tags) == 8); - - yaffs_pack_tags1(&pt1, etags); - yaffs_calc_tags_ecc((struct yaffs_tags *)&pt1); - - /* When deleting a chunk, the upper layer provides only skeletal - * etags, one with is_deleted set. However, we need to update the - * tags, not erase them completely. So we use the NAND write property - * that only zeroed-bits stick and set tag bytes to all-ones and - * zero just the (not) deleted bit. - */ - - if (dev->param.tags_9bytes) { - ((u8 *) &pt1)[8] = 0xff; - if (etags->is_deleted) { - memset(&pt1, 0xff, 8); - /* zero page_status byte to indicate deleted */ - ((u8 *) &pt1)[8] = 0; - } - } else { - if (etags->is_deleted) { - memset(&pt1, 0xff, 8); - /* clear delete status bit to indicate deleted */ - pt1.deleted = 0; - } - } - - memset(&ops, 0, sizeof(ops)); - ops.mode = MTD_OPS_AUTO_OOB; - ops.len = (data) ? chunk_bytes : 0; - ops.ooblen = dev->param.tags_9bytes ? 9 : 8; - ops.datbuf = (u8 *) data; - ops.oobbuf = (u8 *) &pt1; - - retval = mtd->write_oob(mtd, addr, &ops); - if (retval) { - yaffs_trace(YAFFS_TRACE_MTD, - "write_oob failed, chunk %d, mtd error %d", - nand_chunk, retval); - } - return retval ? YAFFS_FAIL : YAFFS_OK; -} - -/* Return with empty ExtendedTags but add ecc_result. - */ -static int rettags(struct yaffs_ext_tags *etags, int ecc_result, int retval) -{ - if (etags) { - memset(etags, 0, sizeof(*etags)); - etags->ecc_result = ecc_result; - } - return retval; -} - -/* Read a chunk (page) from NAND. - * - * Caller expects ExtendedTags data to be usable even on error; that is, - * all members except ecc_result and block_bad are zeroed. - * - * - Check ECC results for data (if applicable) - * - Check for blank/erased block (return empty ExtendedTags if blank) - * - Check the packed_tags1 mini-ECC (correct if necessary/possible) - * - Convert packed_tags1 to ExtendedTags - * - Update ecc_result and block_bad members to refect state. - * - * Returns YAFFS_OK or YAFFS_FAIL. - */ -int nandmtd1_read_chunk_tags(struct yaffs_dev *dev, - int nand_chunk, u8 *data, - struct yaffs_ext_tags *etags) -{ - struct mtd_info *mtd = yaffs_dev_to_mtd(dev); - int chunk_bytes = dev->data_bytes_per_chunk; - loff_t addr = ((loff_t) nand_chunk) * chunk_bytes; - int eccres = YAFFS_ECC_RESULT_NO_ERROR; - struct mtd_oob_ops ops; - struct yaffs_packed_tags1 pt1; - int retval; - int deleted; - - memset(&ops, 0, sizeof(ops)); - ops.mode = MTD_OPS_AUTO_OOB; - ops.len = (data) ? chunk_bytes : 0; - ops.ooblen = dev->param.tags_9bytes ? 9 : 8; - ops.datbuf = data; - ops.oobbuf = (u8 *) &pt1; - - /* Read page and oob using MTD. - * Check status and determine ECC result. - */ - retval = mtd->read_oob(mtd, addr, &ops); - if (retval) { - yaffs_trace(YAFFS_TRACE_MTD, - "read_oob failed, chunk %d, mtd error %d", - nand_chunk, retval); - } - - switch (retval) { - case 0: - /* no error */ - break; - - case -EUCLEAN: - /* MTD's ECC fixed the data */ - eccres = YAFFS_ECC_RESULT_FIXED; - dev->n_ecc_fixed++; - break; - - case -EBADMSG: - /* MTD's ECC could not fix the data */ - dev->n_ecc_unfixed++; - /* fall into... */ - default: - rettags(etags, YAFFS_ECC_RESULT_UNFIXED, 0); - etags->block_bad = (mtd->block_isbad) (mtd, addr); - return YAFFS_FAIL; - } - - /* Check for a blank/erased chunk. - */ - if (yaffs_check_ff((u8 *) &pt1, 8)) { - /* when blank, upper layers want ecc_result to be <= NO_ERROR */ - return rettags(etags, YAFFS_ECC_RESULT_NO_ERROR, YAFFS_OK); - } -#ifndef CONFIG_YAFFS_9BYTE_TAGS - /* Read deleted status (bit) then return it to it's non-deleted - * state before performing tags mini-ECC check. pt1.deleted is - * inverted. - */ - deleted = !pt1.deleted; - pt1.deleted = 1; -#else - deleted = (hweight8(((u8 *) &pt1)[8]) < 7); -#endif - - /* Check the packed tags mini-ECC and correct if necessary/possible. - */ - retval = yaffs_check_tags_ecc((struct yaffs_tags *)&pt1); - switch (retval) { - case 0: - /* no tags error, use MTD result */ - break; - case 1: - /* recovered tags-ECC error */ - dev->n_tags_ecc_fixed++; - if (eccres == YAFFS_ECC_RESULT_NO_ERROR) - eccres = YAFFS_ECC_RESULT_FIXED; - break; - default: - /* unrecovered tags-ECC error */ - dev->n_tags_ecc_unfixed++; - return rettags(etags, YAFFS_ECC_RESULT_UNFIXED, YAFFS_FAIL); - } - - /* Unpack the tags to extended form and set ECC result. - * [set should_be_ff just to keep yaffs_unpack_tags1 happy] - */ - pt1.should_be_ff = 0xffffffff; - yaffs_unpack_tags1(etags, &pt1); - etags->ecc_result = eccres; - - /* Set deleted state */ - etags->is_deleted = deleted; - return YAFFS_OK; -} - -/* Mark a block bad. - * - * This is a persistant state. - * Use of this function should be rare. - * - * Returns YAFFS_OK or YAFFS_FAIL. - */ -int nandmtd1_mark_block_bad(struct yaffs_dev *dev, int block_no) -{ - struct mtd_info *mtd = yaffs_dev_to_mtd(dev); - int blocksize = dev->param.chunks_per_block * dev->data_bytes_per_chunk; - int retval; - - yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, - "marking block %d bad", block_no); - - retval = mtd->block_markbad(mtd, (loff_t) blocksize * block_no); - return (retval) ? YAFFS_FAIL : YAFFS_OK; -} - -/* Check any MTD prerequists. - * - * Returns YAFFS_OK or YAFFS_FAIL. - */ -static int nandmtd1_test_prerequists(struct yaffs_dev *dev, - struct mtd_info *mtd) -{ - /* 2.6.18 has mtd->ecclayout->oobavail */ - /* 2.6.21 has mtd->ecclayout->oobavail and mtd->oobavail */ - int oobavail = mtd->ecclayout->oobavail; - - if (oobavail < (dev->param.tags_9bytes ? 9 : 8)) { - yaffs_trace(YAFFS_TRACE_ERROR, - "mtd device has only %d bytes for tags, need %d", - oobavail, (dev->param.tags_9bytes ? 9 : 8)); - return YAFFS_FAIL; - } - return YAFFS_OK; -} - -/* Query for the current state of a specific block. - * - * Examine the tags of the first chunk of the block and return the state: - * - YAFFS_BLOCK_STATE_DEAD, the block is marked bad - * - YAFFS_BLOCK_STATE_NEEDS_SCAN, the block is in use - * - YAFFS_BLOCK_STATE_EMPTY, the block is clean - * - * Always returns YAFFS_OK. - */ -int nandmtd1_query_block(struct yaffs_dev *dev, int block_no, - enum yaffs_block_state *state_ptr, u32 * seq_ptr) -{ - struct mtd_info *mtd = yaffs_dev_to_mtd(dev); - int chunk_num = block_no * dev->param.chunks_per_block; - loff_t addr = (loff_t) chunk_num * dev->data_bytes_per_chunk; - struct yaffs_ext_tags etags; - int state = YAFFS_BLOCK_STATE_DEAD; - int seqnum = 0; - int retval; - - /* We don't yet have a good place to test for MTD config prerequists. - * Do it here as we are called during the initial scan. - */ - if (nandmtd1_test_prerequists(dev, mtd) != YAFFS_OK) - return YAFFS_FAIL; - - retval = nandmtd1_read_chunk_tags(dev, chunk_num, NULL, &etags); - etags.block_bad = (mtd->block_isbad) (mtd, addr); - if (etags.block_bad) { - yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, - "block %d is marked bad", block_no); - state = YAFFS_BLOCK_STATE_DEAD; - } else if (etags.ecc_result != YAFFS_ECC_RESULT_NO_ERROR) { - /* bad tags, need to look more closely */ - state = YAFFS_BLOCK_STATE_NEEDS_SCAN; - } else if (etags.chunk_used) { - state = YAFFS_BLOCK_STATE_NEEDS_SCAN; - seqnum = etags.seq_number; - } else { - state = YAFFS_BLOCK_STATE_EMPTY; - } - - *state_ptr = state; - *seq_ptr = seqnum; - - /* query always succeeds */ - return YAFFS_OK; -} diff --git a/yaffs_mtdif2.h b/yaffs_mtdif2.h deleted file mode 100644 index d4d1858..0000000 --- a/yaffs_mtdif2.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * YAFFS: Yet another Flash File System . A NAND-flash specific file system. - * - * Copyright (C) 2002-2011 Aleph One Ltd. - * for Toby Churchill Ltd and Brightstar Engineering - * - * Created by Charles Manning - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 as - * published by the Free Software Foundation. - * - * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. - */ - -#ifndef __YAFFS_MTDIF2_H__ -#define __YAFFS_MTDIF2_H__ - -#include "yaffs_guts.h" -int nandmtd2_write_chunk_tags(struct yaffs_dev *dev, int nand_chunk, - const u8 *data, - const struct yaffs_ext_tags *tags); -int nandmtd2_read_chunk_tags(struct yaffs_dev *dev, int nand_chunk, - u8 *data, struct yaffs_ext_tags *tags); -int nandmtd2_mark_block_bad(struct yaffs_dev *dev, int block_no); -int nandmtd2_query_block(struct yaffs_dev *dev, int block_no, - enum yaffs_block_state *state, u32 *seq_number); - -#endif diff --git a/yaffs_mtdif2_multi.c b/yaffs_mtdif2_multi.c deleted file mode 100644 index 18ac992..0000000 --- a/yaffs_mtdif2_multi.c +++ /dev/null @@ -1,268 +0,0 @@ -/* - * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. - * - * Copyright (C) 2002-2011 Aleph One Ltd. - * for Toby Churchill Ltd and Brightstar Engineering - * - * Created by Charles Manning - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -/* mtd interface for YAFFS2 */ - -#include "yportenv.h" -#include "yaffs_trace.h" - -#include "yaffs_mtdif2.h" - -#include "linux/mtd/mtd.h" -#include "linux/types.h" -#include "linux/time.h" - -#include "yaffs_packedtags2.h" - -#include "yaffs_linux.h" - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) -#define MTD_OPS_AUTO_OOB MTD_OOB_AUTO -#endif - - - -/* NB For use with inband tags.... - * We assume that the data buffer is of size total_bytes_per_chunk so - * that we can also use it to load the tags. - */ -int nandmtd2_write_chunk_tags(struct yaffs_dev *dev, int nand_chunk, - const u8 *data, - const struct yaffs_ext_tags *tags) -{ - struct mtd_info *mtd = yaffs_dev_to_mtd(dev); -#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17)) - struct mtd_oob_ops ops; -#else - size_t dummy; -#endif - int retval = 0; - - loff_t addr; - - struct yaffs_packed_tags2 pt; - - int packed_tags_size = - dev->param.no_tags_ecc ? sizeof(pt.t) : sizeof(pt); - void *packed_tags_ptr = - dev->param.no_tags_ecc ? (void *)&pt.t : (void *)&pt; - - yaffs_trace(YAFFS_TRACE_MTD, - "nandmtd2_write_chunk_tags chunk %d data %p tags %p", - nand_chunk, data, tags); - - addr = ((loff_t) nand_chunk) * dev->param.total_bytes_per_chunk; - - /* 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 (!data || !tags) - BUG(); - else 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); - } else { - yaffs_pack_tags2(&pt, tags, !dev->param.no_tags_ecc); - } - -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) - ops.mode = MTD_OPS_AUTO_OOB; - ops.ooblen = (dev->param.inband_tags) ? 0 : packed_tags_size; - ops.len = dev->param.total_bytes_per_chunk; - ops.ooboffs = 0; - ops.datbuf = (u8 *) data; - ops.oobbuf = (dev->param.inband_tags) ? NULL : packed_tags_ptr; - retval = mtd->write_oob(mtd, addr, &ops); - -#else - if (!dev->param.inband_tags) { - retval = - mtd->write_ecc(mtd, addr, dev->data_bytes_per_chunk, - &dummy, data, (u8 *) packed_tags_ptr, NULL); - } else { - retval = - mtd->write(mtd, addr, dev->param.total_bytes_per_chunk, - &dummy, data); - } -#endif - - if (retval == 0) - return YAFFS_OK; - else - return YAFFS_FAIL; -} - -int nandmtd2_read_chunk_tags(struct yaffs_dev *dev, int nand_chunk, - u8 *data, struct yaffs_ext_tags *tags) -{ - struct mtd_info *mtd = yaffs_dev_to_mtd(dev); -#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17)) - struct mtd_oob_ops ops; -#endif - size_t dummy; - int retval = 0; - int local_data = 0; - - loff_t addr = ((loff_t) nand_chunk) * dev->param.total_bytes_per_chunk; - - struct yaffs_packed_tags2 pt; - - int packed_tags_size = - dev->param.no_tags_ecc ? sizeof(pt.t) : sizeof(pt); - void *packed_tags_ptr = - dev->param.no_tags_ecc ? (void *)&pt.t : (void *)&pt; - - yaffs_trace(YAFFS_TRACE_MTD, - "nandmtd2_read_chunk_tags chunk %d data %p tags %p", - nand_chunk, data, tags); - - if (dev->param.inband_tags) { - - if (!data) { - local_data = 1; - data = yaffs_get_temp_buffer(dev); - } - - } - -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) - if (dev->param.inband_tags || (data && !tags)) - retval = mtd->read(mtd, addr, dev->param.total_bytes_per_chunk, - &dummy, data); - else if (tags) { - ops.mode = MTD_OPS_AUTO_OOB; - ops.ooblen = packed_tags_size; - ops.len = data ? dev->data_bytes_per_chunk : packed_tags_size; - ops.ooboffs = 0; - ops.datbuf = data; - ops.oobbuf = yaffs_dev_to_lc(dev)->spare_buffer; - retval = mtd->read_oob(mtd, addr, &ops); - } -#else - if (!dev->param.inband_tags && data && tags) { - - retval = mtd->read_ecc(mtd, addr, dev->data_bytes_per_chunk, - &dummy, data, dev->spare_buffer, NULL); - } else { - if (data) - retval = - mtd->read(mtd, addr, dev->data_bytes_per_chunk, - &dummy, data); - if (!dev->param.inband_tags && tags) - retval = - mtd->read_oob(mtd, addr, mtd->oobsize, &dummy, - dev->spare_buffer); - } -#endif - - 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) { - memcpy(packed_tags_ptr, - yaffs_dev_to_lc(dev)->spare_buffer, - packed_tags_size); - yaffs_unpack_tags2(tags, &pt, !dev->param.no_tags_ecc); - } - } - - if (local_data) - yaffs_release_temp_buffer(dev, data); - - if (tags && retval == -EBADMSG - && tags->ecc_result == YAFFS_ECC_RESULT_NO_ERROR) { - tags->ecc_result = YAFFS_ECC_RESULT_UNFIXED; - dev->n_ecc_unfixed++; - } - if (tags && retval == -EUCLEAN - && tags->ecc_result == YAFFS_ECC_RESULT_NO_ERROR) { - tags->ecc_result = YAFFS_ECC_RESULT_FIXED; - dev->n_ecc_fixed++; - } - if (retval == 0) - return YAFFS_OK; - else - return YAFFS_FAIL; -} - -int nandmtd2_mark_block_bad(struct yaffs_dev *dev, int block_no) -{ - struct mtd_info *mtd = yaffs_dev_to_mtd(dev); - int retval; - yaffs_trace(YAFFS_TRACE_MTD, - "nandmtd2_mark_block_bad %d", - block_no); - - retval = - mtd->block_markbad(mtd, - block_no * dev->param.chunks_per_block * - dev->param.total_bytes_per_chunk); - - if (retval == 0) - return YAFFS_OK; - else - return YAFFS_FAIL; - -} - -int nandmtd2_query_block(struct yaffs_dev *dev, int block_no, - enum yaffs_block_state *state, u32 *seq_number) -{ - struct mtd_info *mtd = yaffs_dev_to_mtd(dev); - int retval; - - yaffs_trace(YAFFS_TRACE_MTD, "nandmtd2_query_block %d", block_no); - retval = - mtd->block_isbad(mtd, - block_no * dev->param.chunks_per_block * - dev->param.total_bytes_per_chunk); - - if (retval) { - yaffs_trace(YAFFS_TRACE_MTD, "block is bad"); - - *state = YAFFS_BLOCK_STATE_DEAD; - *seq_number = 0; - } else { - struct yaffs_ext_tags t; - nandmtd2_read_chunk_tags(dev, block_no * - dev->param.chunks_per_block, NULL, &t); - - if (t.chunk_used) { - *seq_number = t.seq_number; - *state = YAFFS_BLOCK_STATE_NEEDS_SCAN; - } else { - *seq_number = 0; - *state = YAFFS_BLOCK_STATE_EMPTY; - } - } - yaffs_trace(YAFFS_TRACE_MTD, - "block is bad seq %d state %d", - *seq_number, *state); - - if (retval == 0) - return YAFFS_OK; - else - return YAFFS_FAIL; -} - diff --git a/yaffs_mtdif2_single.c b/yaffs_mtdif2_single.c deleted file mode 100644 index f92c49f..0000000 --- a/yaffs_mtdif2_single.c +++ /dev/null @@ -1,210 +0,0 @@ -/* - * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. - * - * Copyright (C) 2002-2011 Aleph One Ltd. - * for Toby Churchill Ltd and Brightstar Engineering - * - * Created by Charles Manning - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -/* mtd interface for YAFFS2 */ - -#include "yportenv.h" -#include "yaffs_trace.h" -#include "yaffs_mtdif2.h" -#include "yaffs_packedtags2.h" -#include "yaffs_linux.h" -#include "linux/mtd/mtd.h" -#include "linux/types.h" -#include "linux/time.h" -#include "mtd/mtd-abi.h" - - -/* NB For use with inband tags.... - * We assume that the data buffer is of size total_bytes_per_chunk so that - * we can also use it to load the tags. - */ -int nandmtd2_write_chunk_tags(struct yaffs_dev *dev, int nand_chunk, - const u8 *data, - const struct yaffs_ext_tags *tags) -{ - struct mtd_info *mtd = yaffs_dev_to_mtd(dev); - struct mtd_oob_ops ops; - int retval = 0; - loff_t addr; - struct yaffs_packed_tags2 pt; - int packed_tags_size = - dev->param.no_tags_ecc ? sizeof(pt.t) : sizeof(pt); - void *packed_tags_ptr = - dev->param.no_tags_ecc ? (void *)&pt.t : (void *)&pt; - - yaffs_trace(YAFFS_TRACE_MTD, - "nandmtd2_write_chunk_tags chunk %d data %p tags %p", - nand_chunk, data, tags); - - addr = ((loff_t) nand_chunk) * dev->param.total_bytes_per_chunk; - - /* 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 (!data || !tags) - BUG(); - else 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); - } else { - yaffs_pack_tags2(&pt, tags, !dev->param.no_tags_ecc); - } - - ops.mode = MTD_OPS_AUTO_OOB; - ops.ooblen = (dev->param.inband_tags) ? 0 : packed_tags_size; - ops.len = dev->param.total_bytes_per_chunk; - ops.ooboffs = 0; - ops.datbuf = (u8 *) data; - ops.oobbuf = (dev->param.inband_tags) ? NULL : packed_tags_ptr; - retval = mtd->write_oob(mtd, addr, &ops); - - if (retval == 0) - return YAFFS_OK; - - return YAFFS_FAIL; -} - -int nandmtd2_read_chunk_tags(struct yaffs_dev *dev, int nand_chunk, - u8 *data, struct yaffs_ext_tags *tags) -{ - struct mtd_info *mtd = yaffs_dev_to_mtd(dev); - struct mtd_oob_ops ops; - size_t dummy; - int retval = 0; - int local_data = 0; - loff_t addr = ((loff_t) nand_chunk) * dev->param.total_bytes_per_chunk; - struct yaffs_packed_tags2 pt; - int packed_tags_size = - dev->param.no_tags_ecc ? sizeof(pt.t) : sizeof(pt); - void *packed_tags_ptr = - dev->param.no_tags_ecc ? (void *)&pt.t : (void *)&pt; - - yaffs_trace(YAFFS_TRACE_MTD, - "nandmtd2_read_chunk_tags chunk %d data %p tags %p", - nand_chunk, data, tags); - - if (dev->param.inband_tags && !data) { - local_data = 1; - data = yaffs_get_temp_buffer(dev); - } - - if (dev->param.inband_tags || (data && !tags)) { - retval = mtd->read(mtd, addr, dev->param.total_bytes_per_chunk, - &dummy, data); - } else if (tags) { - ops.mode = MTD_OPS_AUTO_OOB; - ops.ooblen = packed_tags_size; - ops.len = data ? dev->data_bytes_per_chunk : packed_tags_size; - ops.ooboffs = 0; - ops.datbuf = data; - ops.oobbuf = yaffs_dev_to_lc(dev)->spare_buffer; - retval = mtd->read_oob(mtd, addr, &ops); - } - - if (dev->param.inband_tags && 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) { - memcpy(packed_tags_ptr, - yaffs_dev_to_lc(dev)->spare_buffer, - packed_tags_size); - yaffs_unpack_tags2(tags, &pt, !dev->param.no_tags_ecc); - } - - if (local_data) - yaffs_release_temp_buffer(dev, data); - - if (tags && retval == -EBADMSG && - tags->ecc_result == YAFFS_ECC_RESULT_NO_ERROR) { - tags->ecc_result = YAFFS_ECC_RESULT_UNFIXED; - dev->n_ecc_unfixed++; - } - if (tags && retval == -EUCLEAN && - tags->ecc_result == YAFFS_ECC_RESULT_NO_ERROR) { - tags->ecc_result = YAFFS_ECC_RESULT_FIXED; - dev->n_ecc_fixed++; - } - - if (retval == 0) - return YAFFS_OK; - - return YAFFS_FAIL; -} - -int nandmtd2_mark_block_bad(struct yaffs_dev *dev, int block_no) -{ - struct mtd_info *mtd = yaffs_dev_to_mtd(dev); - int retval; - - yaffs_trace(YAFFS_TRACE_MTD, - "nandmtd2_mark_block_bad %d", block_no); - - retval = - mtd->block_markbad(mtd, - block_no * dev->param.chunks_per_block * - dev->param.total_bytes_per_chunk); - - if (retval == 0) - return YAFFS_OK; - - return YAFFS_FAIL; -} - -int nandmtd2_query_block(struct yaffs_dev *dev, int block_no, - enum yaffs_block_state *state, u32 * seq_number) -{ - struct mtd_info *mtd = yaffs_dev_to_mtd(dev); - int retval; - - yaffs_trace(YAFFS_TRACE_MTD, "nandmtd2_query_block %d", block_no); - retval = - mtd->block_isbad(mtd, - block_no * dev->param.chunks_per_block * - dev->param.total_bytes_per_chunk); - - if (retval) { - yaffs_trace(YAFFS_TRACE_MTD, "block is bad"); - - *state = YAFFS_BLOCK_STATE_DEAD; - *seq_number = 0; - } else { - struct yaffs_ext_tags t; - - nandmtd2_read_chunk_tags(dev, block_no * - dev->param.chunks_per_block, NULL, &t); - - if (t.chunk_used) { - *seq_number = t.seq_number; - *state = YAFFS_BLOCK_STATE_NEEDS_SCAN; - } else { - *seq_number = 0; - *state = YAFFS_BLOCK_STATE_EMPTY; - } - } - yaffs_trace(YAFFS_TRACE_MTD, - "block is bad seq %d state %d", *seq_number, *state); - - if (retval == 0) - return YAFFS_OK; - - return YAFFS_FAIL; -} diff --git a/yaffs_mtdif_multi.c b/yaffs_mtdif_multi.c new file mode 100644 index 0000000..e61699d --- /dev/null +++ b/yaffs_mtdif_multi.c @@ -0,0 +1,223 @@ +/* + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. + * + * Copyright (C) 2002-2011 Aleph One Ltd. + * for Toby Churchill Ltd and Brightstar Engineering + * + * Created by Charles Manning + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include "yportenv.h" + +#include "yaffs_mtdif.h" + +#include "linux/mtd/mtd.h" +#include "linux/types.h" +#include "linux/time.h" +#include "linux/mtd/nand.h" +#include "linux/kernel.h" +#include "linux/version.h" +#include "linux/types.h" + +#include "yaffs_trace.h" +#include "yaffs_guts.h" +#include "yaffs_linux.h" + + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) +#define MTD_OPS_AUTO_OOB MTD_OOB_AUTO +#endif + + +int nandmtd_erase_block(struct yaffs_dev *dev, int block_no) +{ + struct mtd_info *mtd = yaffs_dev_to_mtd(dev); + u32 addr = + ((loff_t) block_no) * dev->param.total_bytes_per_chunk * + dev->param.chunks_per_block; + struct erase_info ei; + int retval = 0; + + ei.mtd = mtd; + ei.addr = addr; + ei.len = dev->param.total_bytes_per_chunk * dev->param.chunks_per_block; + ei.time = 1000; + ei.retries = 2; + ei.callback = NULL; + ei.priv = (u_long) dev; + + retval = mtd->erase(mtd, &ei); + + if (retval == 0) + return YAFFS_OK; + + return YAFFS_FAIL; +} + + +static int yaffs_mtd_write(struct yaffs_dev *dev, int nand_chunk, + const u8 *data, int data_len, + const u8 *oob, int oob_len) +{ + struct mtd_info *mtd = yaffs_dev_to_mtd(dev); + loff_t addr; + struct mtd_oob_ops ops; + int retval; + + addr = ((loff_t) nand_chunk) * dev->param.total_bytes_per_chunk; + memset(&ops, 0, sizeof(ops)); + ops.mode = MTD_OPS_AUTO_OOB; + ops.len = (data) ? data_len : 0; + ops.ooblen = oob_len; + ops.datbuf = (u8 *)data; + ops.oobbuf = (u8 *)oob; + + retval = mtd->write_oob(mtd, addr, &ops); + if (retval) { + yaffs_trace(YAFFS_TRACE_MTD, + "write_oob failed, chunk %d, mtd error %d", + nand_chunk, retval); + } + return retval ? YAFFS_FAIL : YAFFS_OK; +} + +static int yaffs_mtd_read(struct yaffs_dev *dev, int nand_chunk, + u8 *data, int data_len, + u8 *oob, int oob_len, + enum yaffs_ecc_result *ecc_result) +{ + struct mtd_info *mtd = yaffs_dev_to_mtd(dev); + loff_t addr; + struct mtd_oob_ops ops; + int retval; + + addr = ((loff_t) nand_chunk) * dev->data_bytes_per_chunk; + memset(&ops, 0, sizeof(ops)); + ops.mode = MTD_OPS_AUTO_OOB; + ops.len = (data) ? data_len : 0; + ops.ooblen = oob_len; + ops.datbuf = data; + ops.oobbuf = oob; + +#if (MTD_VERSION_CODE < MTD_VERSION(2, 6, 20)) + /* In MTD 2.6.18 to 2.6.19 nand_base.c:nand_do_read_oob() has a bug; + * help it out with ops.len = ops.ooblen when ops.datbuf == NULL. + */ + ops.len = (ops.datbuf) ? ops.len : ops.ooblen; +#endif + /* Read page and oob using MTD. + * Check status and determine ECC result. + */ + retval = mtd->read_oob(mtd, addr, &ops); + if (retval) + yaffs_trace(YAFFS_TRACE_MTD, + "read_oob failed, chunk %d, mtd error %d", + nand_chunk, retval); + + switch (retval) { + case 0: + /* no error */ + if(ecc_result) + *ecc_result = YAFFS_ECC_RESULT_NO_ERROR; + break; + + case -EUCLEAN: + /* MTD's ECC fixed the data */ + if(ecc_result) + *ecc_result = YAFFS_ECC_RESULT_FIXED; + dev->n_ecc_fixed++; + break; + + case -EBADMSG: + default: + /* MTD's ECC could not fix the data */ + dev->n_ecc_unfixed++; + if(ecc_result) + *ecc_result = YAFFS_ECC_RESULT_UNFIXED; + return YAFFS_FAIL; + } + + return YAFFS_OK; +} + +static int yaffs_mtd_erase(struct yaffs_dev *dev, int block_no) +{ + struct mtd_info *mtd = yaffs_dev_to_mtd(dev); + + loff_t addr; + struct erase_info ei; + int retval = 0; + u32 block_size; + + block_size = dev->param.total_bytes_per_chunk * + dev->param.chunks_per_block; + addr = ((loff_t) block_no) * block_size; + + ei.mtd = mtd; + ei.addr = addr; + ei.len = block_size; + ei.time = 1000; + ei.retries = 2; + ei.callback = NULL; + ei.priv = (u_long) dev; + + retval = mtd->erase(mtd, &ei); + + if (retval == 0) + return YAFFS_OK; + + return YAFFS_FAIL; +} + +static int yaffs_mtd_mark_bad(struct yaffs_dev *dev, int block_no) +{ + struct mtd_info *mtd = yaffs_dev_to_mtd(dev); + int blocksize = dev->param.chunks_per_block * dev->data_bytes_per_chunk; + int retval; + + yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, "marking block %d bad", block_no); + + retval = mtd->block_markbad(mtd, (loff_t) blocksize * block_no); + return (retval) ? YAFFS_FAIL : YAFFS_OK; +} + +static int yaffs_mtd_check_bad(struct yaffs_dev *dev, int block_no) +{ + struct mtd_info *mtd = yaffs_dev_to_mtd(dev); + int blocksize = dev->param.chunks_per_block * dev->data_bytes_per_chunk; + int retval; + + yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, "checking block %d bad", block_no); + + retval = mtd->block_isbad(mtd, (loff_t) blocksize * block_no); + return (retval) ? YAFFS_FAIL : YAFFS_OK; +} + +static int yaffs_mtd_initialise(struct yaffs_dev *dev) +{ + return YAFFS_OK; +} + +static int yaffs_mtd_deinitialise(struct yaffs_dev *dev) +{ + return YAFFS_OK; +} + + + +void yaffs_mtd_drv_install(struct yaffs_dev *dev) +{ + struct yaffs_driver *drv = &dev->drv; + + drv->drv_write_chunk_fn = yaffs_mtd_write; + drv->drv_read_chunk_fn = yaffs_mtd_read; + drv->drv_erase_fn = yaffs_mtd_erase; + drv->drv_mark_bad_fn = yaffs_mtd_mark_bad; + drv->drv_check_bad_fn = yaffs_mtd_check_bad; + drv->drv_initialise_fn = yaffs_mtd_initialise; + drv->drv_deinitialise_fn = yaffs_mtd_deinitialise; +} diff --git a/yaffs_nand.c b/yaffs_nand.c index 165d010..9afd5ec 100644 --- a/yaffs_nand.c +++ b/yaffs_nand.c @@ -17,12 +17,17 @@ #include "yaffs_getblockinfo.h" #include "yaffs_summary.h" +static int apply_chunk_offset(struct yaffs_dev *dev, int chunk) +{ + return chunk - dev->chunk_offset; +} + int yaffs_rd_chunk_tags_nand(struct yaffs_dev *dev, int nand_chunk, u8 *buffer, struct yaffs_ext_tags *tags) { int result; struct yaffs_ext_tags local_tags; - int flash_chunk = nand_chunk - dev->chunk_offset; + int flash_chunk = apply_chunk_offset(dev, nand_chunk); dev->n_page_reads++; @@ -30,13 +35,7 @@ int yaffs_rd_chunk_tags_nand(struct yaffs_dev *dev, int nand_chunk, if (!tags) tags = &local_tags; - if (dev->param.read_chunk_tags_fn) - result = - dev->param.read_chunk_tags_fn(dev, flash_chunk, buffer, - tags); - else - result = yaffs_tags_compat_rd(dev, - flash_chunk, buffer, tags); + result = dev->tagger.read_chunk_tags_fn(dev, flash_chunk, buffer, tags); if (tags && tags->ecc_result > YAFFS_ECC_RESULT_NO_ERROR) { struct yaffs_block_info *bi; @@ -53,27 +52,24 @@ int yaffs_wr_chunk_tags_nand(struct yaffs_dev *dev, const u8 *buffer, struct yaffs_ext_tags *tags) { int result; - int flash_chunk = nand_chunk - dev->chunk_offset; + int flash_chunk = apply_chunk_offset(dev, nand_chunk); dev->n_page_writes++; - if (tags) { - tags->seq_number = dev->seq_number; - tags->chunk_used = 1; - yaffs_trace(YAFFS_TRACE_WRITE, - "Writing chunk %d tags %d %d", - nand_chunk, tags->obj_id, tags->chunk_id); - } else { + if (!tags) { yaffs_trace(YAFFS_TRACE_ERROR, "Writing with no tags"); BUG(); return YAFFS_FAIL; } - if (dev->param.write_chunk_tags_fn) - result = dev->param.write_chunk_tags_fn(dev, flash_chunk, + tags->seq_number = dev->seq_number; + tags->chunk_used = 1; + yaffs_trace(YAFFS_TRACE_WRITE, + "Writing chunk %d tags %d %d", + nand_chunk, tags->obj_id, tags->chunk_id); + + result = dev->tagger.write_chunk_tags_fn(dev, flash_chunk, buffer, tags); - else - result = yaffs_tags_compat_wr(dev, flash_chunk, buffer, tags); yaffs_summary_add(dev, tags, nand_chunk); @@ -83,38 +79,40 @@ int yaffs_wr_chunk_tags_nand(struct yaffs_dev *dev, int yaffs_mark_bad(struct yaffs_dev *dev, int block_no) { block_no -= dev->block_offset; - if (dev->param.bad_block_fn) - return dev->param.bad_block_fn(dev, block_no); - - return yaffs_tags_compat_mark_bad(dev, block_no); + dev->n_bad_markings++; + return dev->tagger.mark_bad_fn(dev, block_no); } + int yaffs_query_init_block_state(struct yaffs_dev *dev, int block_no, enum yaffs_block_state *state, u32 *seq_number) { block_no -= dev->block_offset; - if (dev->param.query_block_fn) - return dev->param.query_block_fn(dev, block_no, state, - seq_number); - - return yaffs_tags_compat_query_block(dev, block_no, state, seq_number); + return dev->tagger.query_block_fn(dev, block_no, state, seq_number); } -int yaffs_erase_block(struct yaffs_dev *dev, int flash_block) +int yaffs_erase_block(struct yaffs_dev *dev, int block_no) { int result; - flash_block -= dev->block_offset; + block_no -= dev->block_offset; dev->n_erasures++; - result = dev->param.erase_fn(dev, flash_block); + result = dev->drv.drv_erase_fn(dev, block_no); return result; } int yaffs_init_nand(struct yaffs_dev *dev) { - if (dev->param.initialise_flash_fn) - return dev->param.initialise_flash_fn(dev); + if (dev->drv.drv_initialise_fn) + return dev->drv.drv_initialise_fn(dev); + return YAFFS_OK; +} + +int yaffs_deinit_nand(struct yaffs_dev *dev) +{ + if (dev->drv.drv_deinitialise_fn) + return dev->drv.drv_deinitialise_fn(dev); return YAFFS_OK; } diff --git a/yaffs_nand.h b/yaffs_nand.h index 7134662..804e97a 100644 --- a/yaffs_nand.h +++ b/yaffs_nand.h @@ -34,5 +34,6 @@ int yaffs_query_init_block_state(struct yaffs_dev *dev, int yaffs_erase_block(struct yaffs_dev *dev, int flash_block); int yaffs_init_nand(struct yaffs_dev *dev); +int yaffs_deinit_nand(struct yaffs_dev *dev); #endif diff --git a/yaffs_tagscompat.c b/yaffs_tagscompat.c index 32ba11f..092430b 100644 --- a/yaffs_tagscompat.c +++ b/yaffs_tagscompat.c @@ -22,11 +22,6 @@ static void yaffs_handle_rd_data_error(struct yaffs_dev *dev, int nand_chunk); /********** Tags ECC calculations *********/ -static void yaffs_calc_ecc(const u8 *data, struct yaffs_spare *spare) -{ - yaffs_ecc_calc(data, spare->ecc1); - yaffs_ecc_calc(&data[256], spare->ecc2); -} void yaffs_calc_tags_ecc(struct yaffs_tags *tags) { @@ -127,14 +122,11 @@ static int yaffs_wr_nand(struct yaffs_dev *dev, int nand_chunk, const u8 *data, struct yaffs_spare *spare) { - if (nand_chunk < dev->param.start_block * dev->param.chunks_per_block) { - yaffs_trace(YAFFS_TRACE_ERROR, - "**>> yaffs chunk %d is not valid", - nand_chunk); - return YAFFS_FAIL; - } + int data_size = dev->data_bytes_per_chunk; - return dev->param.write_chunk_fn(dev, nand_chunk, data, spare); + return dev->drv.drv_write_chunk_fn(dev, nand_chunk, + data, data_size, + (u8 *) spare, sizeof(*spare)); } static int yaffs_rd_chunk_nand(struct yaffs_dev *dev, @@ -146,112 +138,77 @@ static int yaffs_rd_chunk_nand(struct yaffs_dev *dev, { int ret_val; struct yaffs_spare local_spare; + int data_size; + int spare_size; + int ecc_result1, ecc_result2; + u8 calc_ecc[3]; if (!spare) { /* If we don't have a real spare, then we use a local one. */ /* Need this for the calculation of the ecc */ spare = &local_spare; } + data_size = dev->data_bytes_per_chunk; + spare_size = sizeof(struct yaffs_spare); - if (!dev->param.use_nand_ecc) { - ret_val = - dev->param.read_chunk_fn(dev, nand_chunk, data, spare); - if (data && correct_errors) { - /* Do ECC correction */ - /* Todo handle any errors */ - int ecc_result1, ecc_result2; - u8 calc_ecc[3]; - - yaffs_ecc_calc(data, calc_ecc); - ecc_result1 = - yaffs_ecc_correct(data, spare->ecc1, calc_ecc); - yaffs_ecc_calc(&data[256], calc_ecc); - ecc_result2 = - yaffs_ecc_correct(&data[256], spare->ecc2, - calc_ecc); - - if (ecc_result1 > 0) { - yaffs_trace(YAFFS_TRACE_ERROR, - "**>>yaffs ecc error fix performed on chunk %d:0", - nand_chunk); - dev->n_ecc_fixed++; - } else if (ecc_result1 < 0) { - yaffs_trace(YAFFS_TRACE_ERROR, - "**>>yaffs ecc error unfixed on chunk %d:0", - nand_chunk); - dev->n_ecc_unfixed++; - } - - if (ecc_result2 > 0) { - yaffs_trace(YAFFS_TRACE_ERROR, - "**>>yaffs ecc error fix performed on chunk %d:1", - nand_chunk); - dev->n_ecc_fixed++; - } else if (ecc_result2 < 0) { - yaffs_trace(YAFFS_TRACE_ERROR, - "**>>yaffs ecc error unfixed on chunk %d:1", - nand_chunk); - dev->n_ecc_unfixed++; - } - - if (ecc_result1 || ecc_result2) { - /* We had a data problem on this page */ - yaffs_handle_rd_data_error(dev, nand_chunk); - } - - if (ecc_result1 < 0 || ecc_result2 < 0) - *ecc_result = YAFFS_ECC_RESULT_UNFIXED; - else if (ecc_result1 > 0 || ecc_result2 > 0) - *ecc_result = YAFFS_ECC_RESULT_FIXED; - else - *ecc_result = YAFFS_ECC_RESULT_NO_ERROR; - } - } else { - /* Must allocate enough memory for spare+2*sizeof(int) */ - /* for ecc results from device. */ - struct yaffs_nand_spare nspare; - - memset(&nspare, 0, sizeof(nspare)); - - ret_val = dev->param.read_chunk_fn(dev, nand_chunk, data, - (struct yaffs_spare *) - &nspare); - memcpy(spare, &nspare, sizeof(struct yaffs_spare)); - if (data && correct_errors) { - if (nspare.eccres1 > 0) { - yaffs_trace(YAFFS_TRACE_ERROR, - "**>>mtd ecc error fix performed on chunk %d:0", - nand_chunk); - } else if (nspare.eccres1 < 0) { - yaffs_trace(YAFFS_TRACE_ERROR, - "**>>mtd ecc error unfixed on chunk %d:0", - nand_chunk); - } - - if (nspare.eccres2 > 0) { - yaffs_trace(YAFFS_TRACE_ERROR, - "**>>mtd ecc error fix performed on chunk %d:1", - nand_chunk); - } else if (nspare.eccres2 < 0) { - yaffs_trace(YAFFS_TRACE_ERROR, - "**>>mtd ecc error unfixed on chunk %d:1", - nand_chunk); - } - - if (nspare.eccres1 || nspare.eccres2) { - /* We had a data problem on this page */ - yaffs_handle_rd_data_error(dev, nand_chunk); - } - - if (nspare.eccres1 < 0 || nspare.eccres2 < 0) - *ecc_result = YAFFS_ECC_RESULT_UNFIXED; - else if (nspare.eccres1 > 0 || nspare.eccres2 > 0) - *ecc_result = YAFFS_ECC_RESULT_FIXED; - else - *ecc_result = YAFFS_ECC_RESULT_NO_ERROR; + if (dev->param.use_nand_ecc) + return dev->drv.drv_read_chunk_fn(dev, nand_chunk, + data, data_size, + (u8 *) spare, spare_size, + ecc_result); - } + + /* Handle the ECC at this level. */ + + ret_val = dev->drv.drv_read_chunk_fn(dev, nand_chunk, + data, data_size, + (u8 *)spare, spare_size, + NULL); + if (!data || !correct_errors) + return ret_val; + + /* Do ECC correction if needed. */ + yaffs_ecc_calc(data, calc_ecc); + ecc_result1 = yaffs_ecc_correct(data, spare->ecc1, calc_ecc); + yaffs_ecc_calc(&data[256], calc_ecc); + ecc_result2 = yaffs_ecc_correct(&data[256], spare->ecc2, calc_ecc); + + if (ecc_result1 > 0) { + yaffs_trace(YAFFS_TRACE_ERROR, + "**>>yaffs ecc error fix performed on chunk %d:0", + nand_chunk); + dev->n_ecc_fixed++; + } else if (ecc_result1 < 0) { + yaffs_trace(YAFFS_TRACE_ERROR, + "**>>yaffs ecc error unfixed on chunk %d:0", + nand_chunk); + dev->n_ecc_unfixed++; } + + if (ecc_result2 > 0) { + yaffs_trace(YAFFS_TRACE_ERROR, + "**>>yaffs ecc error fix performed on chunk %d:1", + nand_chunk); + dev->n_ecc_fixed++; + } else if (ecc_result2 < 0) { + yaffs_trace(YAFFS_TRACE_ERROR, + "**>>yaffs ecc error unfixed on chunk %d:1", + nand_chunk); + dev->n_ecc_unfixed++; + } + + if (ecc_result1 || ecc_result2) { + /* We had a data problem on this page */ + yaffs_handle_rd_data_error(dev, nand_chunk); + } + + if (ecc_result1 < 0 || ecc_result2 < 0) + *ecc_result = YAFFS_ECC_RESULT_UNFIXED; + else if (ecc_result1 > 0 || ecc_result2 > 0) + *ecc_result = YAFFS_ECC_RESULT_FIXED; + else + *ecc_result = YAFFS_ECC_RESULT_NO_ERROR; + return ret_val; } @@ -277,7 +234,7 @@ static void yaffs_handle_rd_data_error(struct yaffs_dev *dev, int nand_chunk) */ } -int yaffs_tags_compat_wr(struct yaffs_dev *dev, +static int yaffs_tags_compat_wr(struct yaffs_dev *dev, int nand_chunk, const u8 *data, const struct yaffs_ext_tags *ext_tags) { @@ -301,15 +258,17 @@ int yaffs_tags_compat_wr(struct yaffs_dev *dev, tags.serial_number = ext_tags->serial_number; - if (!dev->param.use_nand_ecc && data) - yaffs_calc_ecc(data, &spare); + if (!dev->param.use_nand_ecc && data) { + yaffs_ecc_calc(data, spare.ecc1); + yaffs_ecc_calc(&data[256], spare.ecc2); + } yaffs_load_tags_to_spare(&spare, &tags); } return yaffs_wr_nand(dev, nand_chunk, data, &spare); } -int yaffs_tags_compat_rd(struct yaffs_dev *dev, +static int yaffs_tags_compat_rd(struct yaffs_dev *dev, int nand_chunk, u8 *data, struct yaffs_ext_tags *ext_tags) { @@ -358,7 +317,7 @@ int yaffs_tags_compat_rd(struct yaffs_dev *dev, return YAFFS_OK; } -int yaffs_tags_compat_mark_bad(struct yaffs_dev *dev, int flash_block) +static int yaffs_tags_compat_mark_bad(struct yaffs_dev *dev, int flash_block) { struct yaffs_spare spare; @@ -374,7 +333,7 @@ int yaffs_tags_compat_mark_bad(struct yaffs_dev *dev, int flash_block) return YAFFS_OK; } -int yaffs_tags_compat_query_block(struct yaffs_dev *dev, +static int yaffs_tags_compat_query_block(struct yaffs_dev *dev, int block_no, enum yaffs_block_state *state, u32 *seq_number) @@ -391,10 +350,11 @@ int yaffs_tags_compat_query_block(struct yaffs_dev *dev, *seq_number = 0; - yaffs_rd_chunk_nand(dev, block_no * dev->param.chunks_per_block, NULL, - &spare0, &dummy, 1); + /* Look for bad block markers in the first two chunks */ + yaffs_rd_chunk_nand(dev, block_no * dev->param.chunks_per_block, + NULL, &spare0, &dummy, 0); yaffs_rd_chunk_nand(dev, block_no * dev->param.chunks_per_block + 1, - NULL, &spare1, &dummy, 1); + NULL, &spare1, &dummy, 0); if (hweight8(spare0.block_status & spare1.block_status) < 7) *state = YAFFS_BLOCK_STATE_DEAD; @@ -405,3 +365,17 @@ int yaffs_tags_compat_query_block(struct yaffs_dev *dev, return YAFFS_OK; } + +void yaffs_tags_compat_install(struct yaffs_dev *dev) +{ + if(dev->param.is_yaffs2) + return; + if(!dev->tagger.write_chunk_tags_fn) + dev->tagger.write_chunk_tags_fn = yaffs_tags_compat_wr; + if(!dev->tagger.read_chunk_tags_fn) + dev->tagger.read_chunk_tags_fn = yaffs_tags_compat_rd; + if(!dev->tagger.query_block_fn) + dev->tagger.query_block_fn = yaffs_tags_compat_query_block; + if(!dev->tagger.mark_bad_fn) + dev->tagger.mark_bad_fn = yaffs_tags_compat_mark_bad; +} diff --git a/yaffs_tagscompat.h b/yaffs_tagscompat.h index b3c6655..92d298a 100644 --- a/yaffs_tagscompat.h +++ b/yaffs_tagscompat.h @@ -16,7 +16,12 @@ #ifndef __YAFFS_TAGSCOMPAT_H__ #define __YAFFS_TAGSCOMPAT_H__ + #include "yaffs_guts.h" + +#if 0 + + int yaffs_tags_compat_wr(struct yaffs_dev *dev, int nand_chunk, const u8 *data, const struct yaffs_ext_tags *tags); @@ -29,8 +34,11 @@ int yaffs_tags_compat_query_block(struct yaffs_dev *dev, enum yaffs_block_state *state, u32 *seq_number); +#endif + + +void yaffs_tags_compat_install(struct yaffs_dev *dev); void yaffs_calc_tags_ecc(struct yaffs_tags *tags); int yaffs_check_tags_ecc(struct yaffs_tags *tags); -int yaffs_count_bits(u8 byte); #endif diff --git a/yaffs_tagsmarshall.c b/yaffs_tagsmarshall.c new file mode 100644 index 0000000..44a83b1 --- /dev/null +++ b/yaffs_tagsmarshall.c @@ -0,0 +1,199 @@ +/* + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. + * + * Copyright (C) 2002-2011 Aleph One Ltd. + * for Toby Churchill Ltd and Brightstar Engineering + * + * Created by Charles Manning + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include "yaffs_guts.h" +#include "yaffs_trace.h" +#include "yaffs_packedtags2.h" + +static int yaffs_tags_marshall_write(struct yaffs_dev *dev, + int nand_chunk, const u8 *data, + const struct yaffs_ext_tags *tags) +{ + struct yaffs_packed_tags2 pt; + int retval; + + int packed_tags_size = + dev->param.no_tags_ecc ? sizeof(pt.t) : sizeof(pt); + void *packed_tags_ptr = + dev->param.no_tags_ecc ? (void *)&pt.t : (void *)&pt; + + yaffs_trace(YAFFS_TRACE_MTD, + "yaffs_tags_marshall_write 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 (!data || !tags) + BUG(); + else 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); + } else { + yaffs_pack_tags2(&pt, tags, !dev->param.no_tags_ecc); + } + + retval = dev->drv.drv_write_chunk_fn(dev, nand_chunk, + data, dev->param.total_bytes_per_chunk, + (dev->param.inband_tags) ? NULL : packed_tags_ptr, + (dev->param.inband_tags) ? 0 : packed_tags_size); + + return retval; +} + +static int yaffs_tags_marshall_read(struct yaffs_dev *dev, + int nand_chunk, u8 *data, + struct yaffs_ext_tags *tags) +{ + int retval = 0; + int local_data = 0; + u8 spare_buffer[100]; + enum yaffs_ecc_result ecc_result; + + struct yaffs_packed_tags2 pt; + + int packed_tags_size = + dev->param.no_tags_ecc ? sizeof(pt.t) : sizeof(pt); + void *packed_tags_ptr = + dev->param.no_tags_ecc ? (void *)&pt.t : (void *)&pt; + + yaffs_trace(YAFFS_TRACE_MTD, + "yaffs_tags_marshall_read chunk %d data %p tags %p", + nand_chunk, data, tags); + + if (dev->param.inband_tags) { + if (!data) { + local_data = 1; + data = yaffs_get_temp_buffer(dev); + } + } + + if (dev->param.inband_tags || (data && !tags)) + retval = dev->drv.drv_read_chunk_fn(dev, nand_chunk, + data, dev->param.total_bytes_per_chunk, + NULL, 0, + &ecc_result); + else if (tags) + retval = dev->drv.drv_read_chunk_fn(dev, nand_chunk, + data, dev->param.total_bytes_per_chunk, + spare_buffer, packed_tags_size, + &ecc_result); + else + BUG(); + + + 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) { + memcpy(packed_tags_ptr, spare_buffer, packed_tags_size); + yaffs_unpack_tags2(tags, &pt, !dev->param.no_tags_ecc); + } + + if (local_data) + yaffs_release_temp_buffer(dev, data); + + if (tags && ecc_result == YAFFS_ECC_RESULT_UNFIXED) { + tags->ecc_result = YAFFS_ECC_RESULT_UNFIXED; + dev->n_ecc_unfixed++; + } + + if (tags && ecc_result == -YAFFS_ECC_RESULT_FIXED) { + if (tags->ecc_result <= YAFFS_ECC_RESULT_NO_ERROR) + tags->ecc_result = YAFFS_ECC_RESULT_FIXED; + dev->n_ecc_fixed++; + } + + if (ecc_result < YAFFS_ECC_RESULT_UNFIXED) + return YAFFS_OK; + else + return YAFFS_FAIL; +} + +static int yaffs_tags_marshall_query_block(struct yaffs_dev *dev, int block_no, + enum yaffs_block_state *state, + u32 *seq_number) +{ + int retval; + + yaffs_trace(YAFFS_TRACE_MTD, "yaffs_tags_marshall_query_block %d", + block_no); + + retval = dev->drv.drv_check_bad_fn(dev, block_no); + + if (retval== YAFFS_FAIL) { + yaffs_trace(YAFFS_TRACE_MTD, "block is bad"); + + *state = YAFFS_BLOCK_STATE_DEAD; + *seq_number = 0; + } else { + struct yaffs_ext_tags t; + + yaffs_tags_marshall_read(dev, + block_no * dev->param.chunks_per_block, + NULL, &t); + + if (t.chunk_used) { + *seq_number = t.seq_number; + *state = YAFFS_BLOCK_STATE_NEEDS_SCAN; + } else { + *seq_number = 0; + *state = YAFFS_BLOCK_STATE_EMPTY; + } + } + + yaffs_trace(YAFFS_TRACE_MTD, + "block query returns seq %d state %d", + *seq_number, *state); + + if (retval == 0) + return YAFFS_OK; + else + return YAFFS_FAIL; +} + +static int yaffs_tags_marshall_mark_bad(struct yaffs_dev *dev, int block_no) +{ + return dev->drv.drv_mark_bad_fn(dev, block_no); + +} + + +void yaffs_tags_marshall_install(struct yaffs_dev *dev) +{ + if (!dev->param.is_yaffs2) + return; + + if (!dev->tagger.write_chunk_tags_fn) + dev->tagger.write_chunk_tags_fn = yaffs_tags_marshall_write; + + if (!dev->tagger.read_chunk_tags_fn) + dev->tagger.read_chunk_tags_fn = yaffs_tags_marshall_read; + + if (!dev->tagger.query_block_fn) + dev->tagger.query_block_fn = yaffs_tags_marshall_query_block; + + if (!dev->tagger.mark_bad_fn) + dev->tagger.mark_bad_fn = yaffs_tags_marshall_mark_bad; + +} diff --git a/direct/basic-test/yaffs_norif1.h b/yaffs_tagsmarshall.h similarity index 52% rename from direct/basic-test/yaffs_norif1.h rename to yaffs_tagsmarshall.h index 72952b4..bf3e68a 100644 --- a/direct/basic-test/yaffs_norif1.h +++ b/yaffs_tagsmarshall.h @@ -1,5 +1,5 @@ /* - * YAFFS: Yet another Flash File System . A NAND-flash specific file system. + * YAFFS: Yet another Flash File System . A NAND-flash specific file system. * * Copyright (C) 2002-2011 Aleph One Ltd. * for Toby Churchill Ltd and Brightstar Engineering @@ -13,18 +13,10 @@ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. */ - -#ifndef __YAFFS_NOR_IF1_H__ -#define __YAFFS_NOR_IF1_H__ +#ifndef __YAFFS_TAGSMARSHALL_H__ +#define __YAFFS_TAGSMARSHALL_H__ #include "yaffs_guts.h" - -int ynorif1_WriteChunkToNAND(struct yaffs_dev *dev,int nand_chunk,const u8 *data, const struct yaffs_spare *spare); -int ynorif1_ReadChunkFromNAND(struct yaffs_dev *dev,int nand_chunk, u8 *data, struct yaffs_spare *spare); -int ynorif1_EraseBlockInNAND(struct yaffs_dev *dev, int blockNumber); -int ynorif1_InitialiseNAND(struct yaffs_dev *dev); -int ynorif1_Deinitialise_flash_fn(struct yaffs_dev *dev); +void yaffs_tags_marshall_install(struct yaffs_dev *dev); #endif - - diff --git a/yaffs_vfs_multi.c b/yaffs_vfs_multi.c index ce41d6c..3cf6dde 100644 --- a/yaffs_vfs_multi.c +++ b/yaffs_vfs_multi.c @@ -176,8 +176,6 @@ static uint32_t YCALCBLOCKS(uint64_t partition_size, uint32_t block_size) #include "yaffs_linux.h" #include "yaffs_mtdif.h" -#include "yaffs_mtdif1.h" -#include "yaffs_mtdif2.h" unsigned int yaffs_trace_mask = YAFFS_TRACE_BAD_BLOCKS | YAFFS_TRACE_ALWAYS; unsigned int yaffs_wr_attempts = YAFFS_WR_ATTEMPTS; @@ -2475,8 +2473,10 @@ struct mutex yaffs_context_lock; static void yaffs_put_super(struct super_block *sb) { struct yaffs_dev *dev = yaffs_super_to_dev(sb); + struct mtd_info *mtd = yaffs_dev_to_mtd(dev); - yaffs_trace(YAFFS_TRACE_OS, "yaffs_put_super"); + yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_ALWAYS, + "yaffs_put_super"); yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_BACKGROUND, "Shutting down yaffs background thread"); @@ -2488,9 +2488,6 @@ static void yaffs_put_super(struct super_block *sb) yaffs_flush_super(sb, 1); - if (yaffs_dev_to_lc(dev)->put_super_fn) - yaffs_dev_to_lc(dev)->put_super_fn(sb); - yaffs_deinitialise(dev); yaffs_gross_unlock(dev); @@ -2505,18 +2502,18 @@ static void yaffs_put_super(struct super_block *sb) } kfree(dev); -} - -static void yaffs_mtd_put_super(struct super_block *sb) -{ - struct mtd_info *mtd = yaffs_dev_to_mtd(yaffs_super_to_dev(sb)); - if (mtd->sync) + if (mtd && mtd->sync) mtd->sync(mtd); - put_mtd_device(mtd); + if(mtd) + put_mtd_device(mtd); + + yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_ALWAYS, + "yaffs_put_super done"); } + static void yaffs_touch_super(struct yaffs_dev *dev) { struct super_block *sb = yaffs_dev_to_lc(dev)->super; @@ -2831,14 +2828,7 @@ static struct super_block *yaffs_internal_read_super(int yaffs_version, /* Set up the memory size parameters.... */ - n_blocks = - YCALCBLOCKS(mtd->size, - (YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK)); - param->start_block = 0; - param->end_block = n_blocks - 1; - param->chunks_per_block = YAFFS_CHUNKS_PER_BLOCK; - param->total_bytes_per_chunk = YAFFS_BYTES_PER_CHUNK; param->n_reserved_blocks = 5; param->n_caches = (options.no_cache) ? 0 : 10; param->inband_tags = options.inband_tags; @@ -2861,12 +2851,6 @@ static struct super_block *yaffs_internal_read_super(int yaffs_version, /* ... and the functions. */ if (yaffs_version == 2) { - param->write_chunk_tags_fn = nandmtd2_write_chunk_tags; - param->read_chunk_tags_fn = nandmtd2_read_chunk_tags; - param->bad_block_fn = nandmtd2_mark_block_bad; - param->query_block_fn = nandmtd2_query_block; - yaffs_dev_to_lc(dev)->spare_buffer = - kmalloc(mtd->oobsize, GFP_NOFS); param->is_yaffs2 = 1; #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) param->total_bytes_per_chunk = mtd->writesize; @@ -2880,26 +2864,21 @@ static struct super_block *yaffs_internal_read_super(int yaffs_version, param->start_block = 0; param->end_block = n_blocks - 1; } else { -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) - /* use the MTD interface in yaffs_mtdif1.c */ - param->write_chunk_tags_fn = nandmtd1_write_chunk_tags; - param->read_chunk_tags_fn = nandmtd1_read_chunk_tags; - param->bad_block_fn = nandmtd1_mark_block_bad; - param->query_block_fn = nandmtd1_query_block; -#else - param->write_chunk_fn = nandmtd_write_chunk; - param->read_chunk_fn = nandmtd_read_chunk; -#endif param->is_yaffs2 = 0; + n_blocks = YCALCBLOCKS(mtd->size, + YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK); + + param->chunks_per_block = YAFFS_CHUNKS_PER_BLOCK; + param->total_bytes_per_chunk = YAFFS_BYTES_PER_CHUNK; } - /* ... and common functions */ - param->erase_fn = nandmtd_erase_block; - param->initialise_flash_fn = nandmtd_initialise; - yaffs_dev_to_lc(dev)->put_super_fn = yaffs_mtd_put_super; + param->start_block = 0; + param->end_block = n_blocks - 1; + + yaffs_mtd_drv_install(dev); param->sb_dirty_fn = yaffs_touch_super; - param->gc_control = yaffs_gc_control_callback; + param->gc_control_fn = yaffs_gc_control_callback; yaffs_dev_to_lc(dev)->super = sb; diff --git a/yaffs_vfs_single.c b/yaffs_vfs_single.c index 8d41f69..145517b 100644 --- a/yaffs_vfs_single.c +++ b/yaffs_vfs_single.c @@ -1912,6 +1912,7 @@ static void yaffs_fill_inode_from_obj(struct inode *inode, static void yaffs_put_super(struct super_block *sb) { struct yaffs_dev *dev = yaffs_super_to_dev(sb); + struct mtd_info *mtd = yaffs_dev_to_mtd(dev); yaffs_trace(YAFFS_TRACE_OS, "yaffs_put_super"); @@ -1941,16 +1942,14 @@ static void yaffs_put_super(struct super_block *sb) } kfree(dev); -} -static void yaffs_mtd_put_super(struct super_block *sb) -{ - struct mtd_info *mtd = yaffs_dev_to_mtd(yaffs_super_to_dev(sb)); - if (mtd->sync) + + if (mtd && mtd->sync) mtd->sync(mtd); - put_mtd_device(mtd); + if (mtd) + put_mtd_device(mtd); } static const struct super_operations yaffs_super_ops = { @@ -2213,7 +2212,7 @@ static struct super_block *yaffs_internal_read_super(int yaffs_version, yaffs_dev_to_lc(dev)->put_super_fn = yaffs_mtd_put_super; param->sb_dirty_fn = yaffs_touch_super; - param->gc_control = yaffs_gc_control_callback; + param->gc_control_fn = yaffs_gc_control_callback; yaffs_dev_to_lc(dev)->super = sb;