YAFFS code repartitioning proposal


Currently the YAFFS code has the following basic structure.

Yaffs_fs.c (or similar): YAFFS file system interface to hook up YAFFS to the OS. Eg, Under Linux this implements the VFS interface.

Yaffs_guts.c: The file system "guts". This is the (portable) code that implements the YAFFS file sytem algorithms.

Yaffs_mtdif.c (or equivalent): Routines to access the NAND flash.

Yaffc_ecc.c: ECC algorithms.


Currently, yaffs_guts "knows about" ECC, spare (out of band) regions, bad block algorithms and such low-level NAND actions. This means that yaffs_guts gets a bit messy when dealing devices where these algorithms need to be changed. For instance:


This discussion proposes a re-partitioning of the interface between the yaffs_guts. And yaffs_mtd.c to clean up these issues, thus making it easier (and cleaner) to deal with these differences.


The current interface comprises 4 functions:


int WriteChunkToNAND(yaffs_Device *dev,int chunkInNAND, const __u8 *data, yaffs_Spare *spare);

int ReadChunkFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_Spare *spare);

int EraseBlockInNAND(yaffs_Device *dev,int blockInNAND);

int InitialiseNAND(yaffs_Device *dev);


As listed above, of the 4 major partitioning issues, three are related to dealing with the spare area (and it's ECC side-kick). The spare area is used to hold ECC info, bad block markers, and tags. Of these, the ECC and bad block markers are device dependent. The mixing of device dependent and "logical" entities (ie the tags) through the one interface makes the interface rather messy. What I propose is that this interface be re-structured to deal with the logical entities (tags) only.


Also, I propose that the bad block handling algorithm be partitioned off so that it may be easily changed to support different devices.


Ie. the new proposed interface is:

int WriteChunkToNAND(yaffs_Device *dev,int chunkInNAND, const __u8 *data, yaffs_Spare *spare);

int ReadChunkFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_Spare *spare);

int EraseBlockInNAND(yaffs_Device *dev,int blockInNAND);

int InitialiseNAND(yaffs_Device *dev);

int CheckBlockBad(yaffs_Device *dev,int blockInNAND);

int MarkBlockBad(yaffs_Device *dev,int blockInNAND);


Now, the nand interface layer (eg. yaffs_mtdif.c) becomes responsible for handling all ECC, spare to tags mapping and the bad block handling.


For the most part (for existing code and devices), this just means shifting code around rather than writing new code. Once this is done, the code changes to support various devices (as well as future changes to mtd etc) can be better maintained without impacting on yaffs_guts.c. This should make it far easier for both me (the yaffs_guts maintainer) since I won't need to worry about conditional code for various devices and the messiness that causes. It also makes life easier easier for system integrators since they need not go deep into yaffs_guts to make changes.


More details on the functions


int WriteChunkToNAND(yaffs_Device *dev,int chunkInNAND, const __u8 *data, const yaffs_Tags *tags);


When called, data might be NULL, but tags should never be.

Writing can fail due to:

Write error

Verification failure

int ReadChunkFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_Tags *tags);


Data or tags might be NULL in which case these are not written/read.

The function performs all ECC etc, but returns the following results.
Data OK.

ECC corrected

ECC not corrected

Tags OK

Tags corrected

Tags not corrected


int EraseBlockInNAND(yaffs_Device *dev,int blockInNAND);

Erase can return an error if the erasure failed.


int CheckBlockBad(yaffs_Device *dev,int blockInNAND);

Returns a Boolean result as to whether the block is bad or not.


int MarkBlockBad(yaffs_Device *dev,int blockInNAND);

Marks a block as a bad block.


int InitialiseNAND(yaffs_Device *dev);

A call YAFFS makes to the NAND layer during its initialisation (before it uses the other NAND functions). This call can modify some of yaffs_Device structure members.