generic: fold yaffs_cvs_2009_04_24 patch to generic/files
Signed-off-by: Gabor Juhos <juhosg@openwrt.org> SVN-Revision: 34012
This commit is contained in:
parent
73c75e0dd8
commit
56190ed0fc
35 changed files with 3171 additions and 27531 deletions
|
@ -5,7 +5,7 @@
|
|||
config YAFFS_FS
|
||||
tristate "YAFFS2 file system support"
|
||||
default n
|
||||
depends on MTD
|
||||
depends on MTD_BLOCK
|
||||
select YAFFS_YAFFS1
|
||||
select YAFFS_YAFFS2
|
||||
help
|
||||
|
@ -43,7 +43,8 @@ config YAFFS_9BYTE_TAGS
|
|||
format that you need to continue to support. New data written
|
||||
also uses the older-style format. Note: Use of this option
|
||||
generally requires that MTD's oob layout be adjusted to use the
|
||||
older-style format. See notes on tags formats and MTD versions.
|
||||
older-style format. See notes on tags formats and MTD versions
|
||||
in yaffs_mtdif1.c.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
|
@ -109,26 +110,6 @@ config YAFFS_DISABLE_LAZY_LOAD
|
|||
|
||||
If unsure, say N.
|
||||
|
||||
config YAFFS_CHECKPOINT_RESERVED_BLOCKS
|
||||
int "Reserved blocks for checkpointing"
|
||||
depends on YAFFS_YAFFS2
|
||||
default 10
|
||||
help
|
||||
Give the number of Blocks to reserve for checkpointing.
|
||||
Checkpointing saves the state at unmount so that mounting is
|
||||
much faster as a scan of all the flash to regenerate this state
|
||||
is not needed. These Blocks are reserved per partition, so if
|
||||
you have very small partitions the default (10) may be a mess
|
||||
for you. You can set this value to 0, but that does not mean
|
||||
checkpointing is disabled at all. There only won't be any
|
||||
specially reserved blocks for checkpointing, so if there is
|
||||
enough free space on the filesystem, it will be used for
|
||||
checkpointing.
|
||||
|
||||
If unsure, leave at default (10), but don't wonder if there are
|
||||
always 2MB used on your large page device partition (10 x 2k
|
||||
pagesize). When using small partitions or when being very small
|
||||
on space, you probably want to set this to zero.
|
||||
|
||||
config YAFFS_DISABLE_WIDE_TNODES
|
||||
bool "Turn off wide tnodes"
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
obj-$(CONFIG_YAFFS_FS) += yaffs.o
|
||||
|
||||
yaffs-y := yaffs_ecc.o yaffs_fs.o yaffs_guts.o yaffs_checkptrw.o
|
||||
yaffs-y += yaffs_packedtags2.o yaffs_nand.o yaffs_qsort.o
|
||||
yaffs-y += yaffs_packedtags1.o yaffs_packedtags2.o yaffs_nand.o yaffs_qsort.o
|
||||
yaffs-y += yaffs_tagscompat.o yaffs_tagsvalidity.o
|
||||
yaffs-y += yaffs_mtdif1.o yaffs_packedtags1.o
|
||||
yaffs-y += yaffs_mtdif.o yaffs_mtdif2.o
|
||||
yaffs-y += yaffs_mtdif.o yaffs_mtdif1.o yaffs_mtdif2.o
|
||||
|
|
4
target/linux/generic/files/fs/yaffs2/NOTE.openwrt
Normal file
4
target/linux/generic/files/fs/yaffs2/NOTE.openwrt
Normal file
|
@ -0,0 +1,4 @@
|
|||
The yaffs2 source has been fetched from the yaffs2 CVS tree.
|
||||
|
||||
URL: cvs.aleph1.co.uk
|
||||
Version: 2009-09-24
|
|
@ -14,194 +14,135 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* This file is just holds extra declarations used during development.
|
||||
* Most of these are from kernel includes placed here so we can use them in
|
||||
* applications.
|
||||
* This file is just holds extra declarations of macros that would normally
|
||||
* be providesd in the Linux kernel. These macros have been written from
|
||||
* scratch but are functionally equivalent to the Linux ones.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __EXTRAS_H__
|
||||
#define __EXTRAS_H__
|
||||
|
||||
#if defined WIN32
|
||||
#define __inline__ __inline
|
||||
#define new newHack
|
||||
#endif
|
||||
|
||||
#if !(defined __KERNEL__) || (defined WIN32)
|
||||
|
||||
/* User space defines */
|
||||
#if !(defined __KERNEL__)
|
||||
|
||||
/* Definition of types */
|
||||
typedef unsigned char __u8;
|
||||
typedef unsigned short __u16;
|
||||
typedef unsigned __u32;
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Simple doubly linked list implementation.
|
||||
*
|
||||
* Some of the internal functions ("__xxx") are useful when
|
||||
* manipulating whole lists rather than single entries, as
|
||||
* sometimes we already know the next/prev entries and we can
|
||||
* generate better code by using them directly rather than
|
||||
* using the generic single-entry routines.
|
||||
* This is a simple doubly linked list implementation that matches the
|
||||
* way the Linux kernel doubly linked list implementation works.
|
||||
*/
|
||||
|
||||
#define prefetch(x) 1
|
||||
|
||||
struct list_head {
|
||||
struct list_head *next, *prev;
|
||||
struct ylist_head {
|
||||
struct ylist_head *next; /* next in chain */
|
||||
struct ylist_head *prev; /* previous in chain */
|
||||
};
|
||||
|
||||
#define LIST_HEAD_INIT(name) { &(name), &(name) }
|
||||
|
||||
#define LIST_HEAD(name) \
|
||||
struct list_head name = LIST_HEAD_INIT(name)
|
||||
/* Initialise a static list */
|
||||
#define YLIST_HEAD(name) \
|
||||
struct ylist_head name = { &(name), &(name)}
|
||||
|
||||
#define INIT_LIST_HEAD(ptr) do { \
|
||||
(ptr)->next = (ptr); (ptr)->prev = (ptr); \
|
||||
|
||||
|
||||
/* Initialise a list head to an empty list */
|
||||
#define YINIT_LIST_HEAD(p) \
|
||||
do { \
|
||||
(p)->next = (p);\
|
||||
(p)->prev = (p); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Insert a new entry between two known consecutive entries.
|
||||
*
|
||||
* This is only for internal list manipulation where we know
|
||||
* the prev/next entries already!
|
||||
*/
|
||||
static __inline__ void __list_add(struct list_head *new,
|
||||
struct list_head *prev,
|
||||
struct list_head *next)
|
||||
|
||||
/* Add an element to a list */
|
||||
static __inline__ void ylist_add(struct ylist_head *newEntry,
|
||||
struct ylist_head *list)
|
||||
{
|
||||
next->prev = new;
|
||||
new->next = next;
|
||||
new->prev = prev;
|
||||
prev->next = new;
|
||||
struct ylist_head *listNext = list->next;
|
||||
|
||||
list->next = newEntry;
|
||||
newEntry->prev = list;
|
||||
newEntry->next = listNext;
|
||||
listNext->prev = newEntry;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* list_add - add a new entry
|
||||
* @new: new entry to be added
|
||||
* @head: list head to add it after
|
||||
*
|
||||
* Insert a new entry after the specified head.
|
||||
* This is good for implementing stacks.
|
||||
*/
|
||||
static __inline__ void list_add(struct list_head *new, struct list_head *head)
|
||||
static __inline__ void ylist_add_tail(struct ylist_head *newEntry,
|
||||
struct ylist_head *list)
|
||||
{
|
||||
__list_add(new, head, head->next);
|
||||
struct ylist_head *listPrev = list->prev;
|
||||
|
||||
list->prev = newEntry;
|
||||
newEntry->next = list;
|
||||
newEntry->prev = listPrev;
|
||||
listPrev->next = newEntry;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* list_add_tail - add a new entry
|
||||
* @new: new entry to be added
|
||||
* @head: list head to add it before
|
||||
*
|
||||
* Insert a new entry before the specified head.
|
||||
* This is useful for implementing queues.
|
||||
*/
|
||||
static __inline__ void list_add_tail(struct list_head *new,
|
||||
struct list_head *head)
|
||||
|
||||
/* Take an element out of its current list, with or without
|
||||
* reinitialising the links.of the entry*/
|
||||
static __inline__ void ylist_del(struct ylist_head *entry)
|
||||
{
|
||||
__list_add(new, head->prev, head);
|
||||
struct ylist_head *listNext = entry->next;
|
||||
struct ylist_head *listPrev = entry->prev;
|
||||
|
||||
listNext->prev = listPrev;
|
||||
listPrev->next = listNext;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete a list entry by making the prev/next entries
|
||||
* point to each other.
|
||||
*
|
||||
* This is only for internal list manipulation where we know
|
||||
* the prev/next entries already!
|
||||
*/
|
||||
static __inline__ void __list_del(struct list_head *prev,
|
||||
struct list_head *next)
|
||||
static __inline__ void ylist_del_init(struct ylist_head *entry)
|
||||
{
|
||||
next->prev = prev;
|
||||
prev->next = next;
|
||||
ylist_del(entry);
|
||||
entry->next = entry->prev = entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_del - deletes entry from list.
|
||||
* @entry: the element to delete from the list.
|
||||
* Note: list_empty on entry does not return true after this, the entry is
|
||||
* in an undefined state.
|
||||
*/
|
||||
static __inline__ void list_del(struct list_head *entry)
|
||||
|
||||
/* Test if the list is empty */
|
||||
static __inline__ int ylist_empty(struct ylist_head *entry)
|
||||
{
|
||||
__list_del(entry->prev, entry->next);
|
||||
return (entry->next == entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_del_init - deletes entry from list and reinitialize it.
|
||||
* @entry: the element to delete from the list.
|
||||
|
||||
/* ylist_entry takes a pointer to a list entry and offsets it to that
|
||||
* we can find a pointer to the object it is embedded in.
|
||||
*/
|
||||
static __inline__ void list_del_init(struct list_head *entry)
|
||||
{
|
||||
__list_del(entry->prev, entry->next);
|
||||
INIT_LIST_HEAD(entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_empty - tests whether a list is empty
|
||||
* @head: the list to test.
|
||||
|
||||
#define ylist_entry(entry, type, member) \
|
||||
((type *)((char *)(entry)-(unsigned long)(&((type *)NULL)->member)))
|
||||
|
||||
|
||||
/* ylist_for_each and list_for_each_safe iterate over lists.
|
||||
* ylist_for_each_safe uses temporary storage to make the list delete safe
|
||||
*/
|
||||
static __inline__ int list_empty(struct list_head *head)
|
||||
{
|
||||
return head->next == head;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_splice - join two lists
|
||||
* @list: the new list to add.
|
||||
* @head: the place to add it in the first list.
|
||||
*/
|
||||
static __inline__ void list_splice(struct list_head *list,
|
||||
struct list_head *head)
|
||||
{
|
||||
struct list_head *first = list->next;
|
||||
#define ylist_for_each(itervar, list) \
|
||||
for (itervar = (list)->next; itervar != (list); itervar = itervar->next)
|
||||
|
||||
if (first != list) {
|
||||
struct list_head *last = list->prev;
|
||||
struct list_head *at = head->next;
|
||||
#define ylist_for_each_safe(itervar, saveVar, list) \
|
||||
for (itervar = (list)->next, saveVar = (list)->next->next; \
|
||||
itervar != (list); itervar = saveVar, saveVar = saveVar->next)
|
||||
|
||||
first->prev = head;
|
||||
head->next = first;
|
||||
|
||||
last->next = at;
|
||||
at->prev = last;
|
||||
}
|
||||
}
|
||||
#if !(defined __KERNEL__)
|
||||
|
||||
/**
|
||||
* list_entry - get the struct for this entry
|
||||
* @ptr: the &struct list_head pointer.
|
||||
* @type: the type of the struct this is embedded in.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_entry(ptr, type, member) \
|
||||
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
|
||||
|
||||
/**
|
||||
* list_for_each - iterate over a list
|
||||
* @pos: the &struct list_head to use as a loop counter.
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each(pos, head) \
|
||||
for (pos = (head)->next, prefetch(pos->next); pos != (head); \
|
||||
pos = pos->next, prefetch(pos->next))
|
||||
#ifndef WIN32
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CONFIG_YAFFS_PROVIDE_DEFS
|
||||
/* File types */
|
||||
|
||||
/**
|
||||
* list_for_each_safe - iterate over a list safe against removal
|
||||
* of list entry
|
||||
* @pos: the &struct list_head to use as a loop counter.
|
||||
* @n: another &struct list_head to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each_safe(pos, n, head) \
|
||||
for (pos = (head)->next, n = pos->next; pos != (head); \
|
||||
pos = n, n = pos->next)
|
||||
|
||||
/*
|
||||
* File types
|
||||
*/
|
||||
#define DT_UNKNOWN 0
|
||||
#define DT_FIFO 1
|
||||
#define DT_CHR 2
|
||||
|
@ -212,6 +153,7 @@ static __inline__ void list_splice(struct list_head *list,
|
|||
#define DT_SOCK 12
|
||||
#define DT_WHT 14
|
||||
|
||||
|
||||
#ifndef WIN32
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
@ -227,10 +169,6 @@ static __inline__ void list_splice(struct list_head *list,
|
|||
#define ATTR_ATIME 16
|
||||
#define ATTR_MTIME 32
|
||||
#define ATTR_CTIME 64
|
||||
#define ATTR_ATIME_SET 128
|
||||
#define ATTR_MTIME_SET 256
|
||||
#define ATTR_FORCE 512 /* Not a change, but a change it */
|
||||
#define ATTR_ATTR_FLAG 1024
|
||||
|
||||
struct iattr {
|
||||
unsigned int ia_valid;
|
||||
|
@ -244,21 +182,15 @@ struct iattr {
|
|||
unsigned int ia_attr_flags;
|
||||
};
|
||||
|
||||
#define KERN_DEBUG
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#ifndef WIN32
|
||||
#include <linux/types.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/stat.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if defined WIN32
|
||||
#undef new
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -27,12 +27,12 @@
|
|||
|
||||
/* Default: Not selected */
|
||||
/* Meaning: Yaffs does its own ECC, rather than using MTD ECC */
|
||||
//#define CONFIG_YAFFS_DOES_ECC
|
||||
/* #define CONFIG_YAFFS_DOES_ECC */
|
||||
|
||||
/* Default: Not selected */
|
||||
/* Meaning: ECC byte order is 'wrong'. Only meaningful if */
|
||||
/* CONFIG_YAFFS_DOES_ECC is set */
|
||||
//#define CONFIG_YAFFS_ECC_WRONG_ORDER
|
||||
/* #define CONFIG_YAFFS_ECC_WRONG_ORDER */
|
||||
|
||||
/* Default: Selected */
|
||||
/* Meaning: Disables testing whether chunks are erased before writing to them*/
|
||||
|
@ -54,11 +54,11 @@ that you need to continue to support. New data written also uses the
|
|||
older-style format.
|
||||
Note: Use of this option generally requires that MTD's oob layout be
|
||||
adjusted to use the older-style format. See notes on tags formats and
|
||||
MTD versions.
|
||||
MTD versions in yaffs_mtdif1.c.
|
||||
*/
|
||||
/* Default: Not selected */
|
||||
/* Meaning: Use older-style on-NAND data format with pageStatus byte */
|
||||
#define CONFIG_YAFFS_9BYTE_TAGS
|
||||
/* #define CONFIG_YAFFS_9BYTE_TAGS */
|
||||
|
||||
#endif /* YAFFS_OUT_OF_TREE */
|
||||
|
||||
|
|
|
@ -12,48 +12,43 @@
|
|||
*/
|
||||
|
||||
const char *yaffs_checkptrw_c_version =
|
||||
"$Id: yaffs_checkptrw.c,v 1.14 2007-05-15 20:07:40 charles Exp $";
|
||||
"$Id: yaffs_checkptrw.c,v 1.18 2009-03-06 17:20:49 wookey Exp $";
|
||||
|
||||
|
||||
#include "yaffs_checkptrw.h"
|
||||
|
||||
#include "yaffs_getblockinfo.h"
|
||||
|
||||
static int yaffs_CheckpointSpaceOk(yaffs_Device *dev)
|
||||
{
|
||||
|
||||
int blocksAvailable = dev->nErasedBlocks - dev->nReservedBlocks;
|
||||
|
||||
T(YAFFS_TRACE_CHECKPOINT,
|
||||
(TSTR("checkpt blocks available = %d" TENDSTR),
|
||||
blocksAvailable));
|
||||
|
||||
|
||||
return (blocksAvailable <= 0) ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
static int yaffs_CheckpointErase(yaffs_Device *dev)
|
||||
{
|
||||
|
||||
int i;
|
||||
|
||||
|
||||
if(!dev->eraseBlockInNAND)
|
||||
if (!dev->eraseBlockInNAND)
|
||||
return 0;
|
||||
T(YAFFS_TRACE_CHECKPOINT,(TSTR("checking blocks %d to %d"TENDSTR),
|
||||
dev->internalStartBlock,dev->internalEndBlock));
|
||||
T(YAFFS_TRACE_CHECKPOINT, (TSTR("checking blocks %d to %d"TENDSTR),
|
||||
dev->internalStartBlock, dev->internalEndBlock));
|
||||
|
||||
for(i = dev->internalStartBlock; i <= dev->internalEndBlock; i++) {
|
||||
yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,i);
|
||||
if(bi->blockState == YAFFS_BLOCK_STATE_CHECKPOINT){
|
||||
T(YAFFS_TRACE_CHECKPOINT,(TSTR("erasing checkpt block %d"TENDSTR),i));
|
||||
if(dev->eraseBlockInNAND(dev,i- dev->blockOffset /* realign */)){
|
||||
for (i = dev->internalStartBlock; i <= dev->internalEndBlock; i++) {
|
||||
yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, i);
|
||||
if (bi->blockState == YAFFS_BLOCK_STATE_CHECKPOINT) {
|
||||
T(YAFFS_TRACE_CHECKPOINT, (TSTR("erasing checkpt block %d"TENDSTR), i));
|
||||
if (dev->eraseBlockInNAND(dev, i - dev->blockOffset /* realign */)) {
|
||||
bi->blockState = YAFFS_BLOCK_STATE_EMPTY;
|
||||
dev->nErasedBlocks++;
|
||||
dev->nFreeChunks += dev->nChunksPerBlock;
|
||||
}
|
||||
else {
|
||||
dev->markNANDBlockBad(dev,i);
|
||||
} else {
|
||||
dev->markNANDBlockBad(dev, i);
|
||||
bi->blockState = YAFFS_BLOCK_STATE_DEAD;
|
||||
}
|
||||
}
|
||||
|
@ -71,23 +66,23 @@ static void yaffs_CheckpointFindNextErasedBlock(yaffs_Device *dev)
|
|||
int blocksAvailable = dev->nErasedBlocks - dev->nReservedBlocks;
|
||||
T(YAFFS_TRACE_CHECKPOINT,
|
||||
(TSTR("allocating checkpt block: erased %d reserved %d avail %d next %d "TENDSTR),
|
||||
dev->nErasedBlocks,dev->nReservedBlocks,blocksAvailable,dev->checkpointNextBlock));
|
||||
dev->nErasedBlocks, dev->nReservedBlocks, blocksAvailable, dev->checkpointNextBlock));
|
||||
|
||||
if(dev->checkpointNextBlock >= 0 &&
|
||||
dev->checkpointNextBlock <= dev->internalEndBlock &&
|
||||
blocksAvailable > 0){
|
||||
if (dev->checkpointNextBlock >= 0 &&
|
||||
dev->checkpointNextBlock <= dev->internalEndBlock &&
|
||||
blocksAvailable > 0) {
|
||||
|
||||
for(i = dev->checkpointNextBlock; i <= dev->internalEndBlock; i++){
|
||||
yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,i);
|
||||
if(bi->blockState == YAFFS_BLOCK_STATE_EMPTY){
|
||||
for (i = dev->checkpointNextBlock; i <= dev->internalEndBlock; i++) {
|
||||
yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, i);
|
||||
if (bi->blockState == YAFFS_BLOCK_STATE_EMPTY) {
|
||||
dev->checkpointNextBlock = i + 1;
|
||||
dev->checkpointCurrentBlock = i;
|
||||
T(YAFFS_TRACE_CHECKPOINT,(TSTR("allocating checkpt block %d"TENDSTR),i));
|
||||
T(YAFFS_TRACE_CHECKPOINT, (TSTR("allocating checkpt block %d"TENDSTR), i));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
T(YAFFS_TRACE_CHECKPOINT,(TSTR("out of checkpt blocks"TENDSTR)));
|
||||
T(YAFFS_TRACE_CHECKPOINT, (TSTR("out of checkpt blocks"TENDSTR)));
|
||||
|
||||
dev->checkpointNextBlock = -1;
|
||||
dev->checkpointCurrentBlock = -1;
|
||||
|
@ -98,30 +93,31 @@ static void yaffs_CheckpointFindNextCheckpointBlock(yaffs_Device *dev)
|
|||
int i;
|
||||
yaffs_ExtendedTags tags;
|
||||
|
||||
T(YAFFS_TRACE_CHECKPOINT,(TSTR("find next checkpt block: start: blocks %d next %d" TENDSTR),
|
||||
T(YAFFS_TRACE_CHECKPOINT, (TSTR("find next checkpt block: start: blocks %d next %d" TENDSTR),
|
||||
dev->blocksInCheckpoint, dev->checkpointNextBlock));
|
||||
|
||||
if(dev->blocksInCheckpoint < dev->checkpointMaxBlocks)
|
||||
for(i = dev->checkpointNextBlock; i <= dev->internalEndBlock; i++){
|
||||
if (dev->blocksInCheckpoint < dev->checkpointMaxBlocks)
|
||||
for (i = dev->checkpointNextBlock; i <= dev->internalEndBlock; i++) {
|
||||
int chunk = i * dev->nChunksPerBlock;
|
||||
int realignedChunk = chunk - dev->chunkOffset;
|
||||
|
||||
dev->readChunkWithTagsFromNAND(dev,realignedChunk,NULL,&tags);
|
||||
T(YAFFS_TRACE_CHECKPOINT,(TSTR("find next checkpt block: search: block %d oid %d seq %d eccr %d" TENDSTR),
|
||||
i, tags.objectId,tags.sequenceNumber,tags.eccResult));
|
||||
dev->readChunkWithTagsFromNAND(dev, realignedChunk,
|
||||
NULL, &tags);
|
||||
T(YAFFS_TRACE_CHECKPOINT, (TSTR("find next checkpt block: search: block %d oid %d seq %d eccr %d" TENDSTR),
|
||||
i, tags.objectId, tags.sequenceNumber, tags.eccResult));
|
||||
|
||||
if(tags.sequenceNumber == YAFFS_SEQUENCE_CHECKPOINT_DATA){
|
||||
if (tags.sequenceNumber == YAFFS_SEQUENCE_CHECKPOINT_DATA) {
|
||||
/* Right kind of block */
|
||||
dev->checkpointNextBlock = tags.objectId;
|
||||
dev->checkpointCurrentBlock = i;
|
||||
dev->checkpointBlockList[dev->blocksInCheckpoint] = i;
|
||||
dev->blocksInCheckpoint++;
|
||||
T(YAFFS_TRACE_CHECKPOINT,(TSTR("found checkpt block %d"TENDSTR),i));
|
||||
T(YAFFS_TRACE_CHECKPOINT, (TSTR("found checkpt block %d"TENDSTR), i));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
T(YAFFS_TRACE_CHECKPOINT,(TSTR("found no more checkpt blocks"TENDSTR)));
|
||||
T(YAFFS_TRACE_CHECKPOINT, (TSTR("found no more checkpt blocks"TENDSTR)));
|
||||
|
||||
dev->checkpointNextBlock = -1;
|
||||
dev->checkpointCurrentBlock = -1;
|
||||
|
@ -133,17 +129,17 @@ int yaffs_CheckpointOpen(yaffs_Device *dev, int forWriting)
|
|||
|
||||
/* Got the functions we need? */
|
||||
if (!dev->writeChunkWithTagsToNAND ||
|
||||
!dev->readChunkWithTagsFromNAND ||
|
||||
!dev->eraseBlockInNAND ||
|
||||
!dev->markNANDBlockBad)
|
||||
!dev->readChunkWithTagsFromNAND ||
|
||||
!dev->eraseBlockInNAND ||
|
||||
!dev->markNANDBlockBad)
|
||||
return 0;
|
||||
|
||||
if(forWriting && !yaffs_CheckpointSpaceOk(dev))
|
||||
if (forWriting && !yaffs_CheckpointSpaceOk(dev))
|
||||
return 0;
|
||||
|
||||
if(!dev->checkpointBuffer)
|
||||
dev->checkpointBuffer = YMALLOC_DMA(dev->nDataBytesPerChunk);
|
||||
if(!dev->checkpointBuffer)
|
||||
if (!dev->checkpointBuffer)
|
||||
dev->checkpointBuffer = YMALLOC_DMA(dev->totalBytesPerChunk);
|
||||
if (!dev->checkpointBuffer)
|
||||
return 0;
|
||||
|
||||
|
||||
|
@ -159,12 +155,10 @@ int yaffs_CheckpointOpen(yaffs_Device *dev, int forWriting)
|
|||
dev->checkpointNextBlock = dev->internalStartBlock;
|
||||
|
||||
/* Erase all the blocks in the checkpoint area */
|
||||
if(forWriting){
|
||||
memset(dev->checkpointBuffer,0,dev->nDataBytesPerChunk);
|
||||
if (forWriting) {
|
||||
memset(dev->checkpointBuffer, 0, dev->nDataBytesPerChunk);
|
||||
dev->checkpointByteOffset = 0;
|
||||
return yaffs_CheckpointErase(dev);
|
||||
|
||||
|
||||
} else {
|
||||
int i;
|
||||
/* Set to a value that will kick off a read */
|
||||
|
@ -174,7 +168,7 @@ int yaffs_CheckpointOpen(yaffs_Device *dev, int forWriting)
|
|||
dev->blocksInCheckpoint = 0;
|
||||
dev->checkpointMaxBlocks = (dev->internalEndBlock - dev->internalStartBlock)/16 + 2;
|
||||
dev->checkpointBlockList = YMALLOC(sizeof(int) * dev->checkpointMaxBlocks);
|
||||
for(i = 0; i < dev->checkpointMaxBlocks; i++)
|
||||
for (i = 0; i < dev->checkpointMaxBlocks; i++)
|
||||
dev->checkpointBlockList[i] = -1;
|
||||
}
|
||||
|
||||
|
@ -191,18 +185,17 @@ int yaffs_GetCheckpointSum(yaffs_Device *dev, __u32 *sum)
|
|||
|
||||
static int yaffs_CheckpointFlushBuffer(yaffs_Device *dev)
|
||||
{
|
||||
|
||||
int chunk;
|
||||
int realignedChunk;
|
||||
|
||||
yaffs_ExtendedTags tags;
|
||||
|
||||
if(dev->checkpointCurrentBlock < 0){
|
||||
if (dev->checkpointCurrentBlock < 0) {
|
||||
yaffs_CheckpointFindNextErasedBlock(dev);
|
||||
dev->checkpointCurrentChunk = 0;
|
||||
}
|
||||
|
||||
if(dev->checkpointCurrentBlock < 0)
|
||||
if (dev->checkpointCurrentBlock < 0)
|
||||
return 0;
|
||||
|
||||
tags.chunkDeleted = 0;
|
||||
|
@ -210,10 +203,10 @@ static int yaffs_CheckpointFlushBuffer(yaffs_Device *dev)
|
|||
tags.chunkId = dev->checkpointPageSequence + 1;
|
||||
tags.sequenceNumber = YAFFS_SEQUENCE_CHECKPOINT_DATA;
|
||||
tags.byteCount = dev->nDataBytesPerChunk;
|
||||
if(dev->checkpointCurrentChunk == 0){
|
||||
if (dev->checkpointCurrentChunk == 0) {
|
||||
/* First chunk we write for the block? Set block state to
|
||||
checkpoint */
|
||||
yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,dev->checkpointCurrentBlock);
|
||||
yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, dev->checkpointCurrentBlock);
|
||||
bi->blockState = YAFFS_BLOCK_STATE_CHECKPOINT;
|
||||
dev->blocksInCheckpoint++;
|
||||
}
|
||||
|
@ -221,28 +214,29 @@ static int yaffs_CheckpointFlushBuffer(yaffs_Device *dev)
|
|||
chunk = dev->checkpointCurrentBlock * dev->nChunksPerBlock + dev->checkpointCurrentChunk;
|
||||
|
||||
|
||||
T(YAFFS_TRACE_CHECKPOINT,(TSTR("checkpoint wite buffer nand %d(%d:%d) objid %d chId %d" TENDSTR),
|
||||
chunk, dev->checkpointCurrentBlock, dev->checkpointCurrentChunk,tags.objectId,tags.chunkId));
|
||||
T(YAFFS_TRACE_CHECKPOINT, (TSTR("checkpoint wite buffer nand %d(%d:%d) objid %d chId %d" TENDSTR),
|
||||
chunk, dev->checkpointCurrentBlock, dev->checkpointCurrentChunk, tags.objectId, tags.chunkId));
|
||||
|
||||
realignedChunk = chunk - dev->chunkOffset;
|
||||
|
||||
dev->writeChunkWithTagsToNAND(dev,realignedChunk,dev->checkpointBuffer,&tags);
|
||||
dev->writeChunkWithTagsToNAND(dev, realignedChunk,
|
||||
dev->checkpointBuffer, &tags);
|
||||
dev->checkpointByteOffset = 0;
|
||||
dev->checkpointPageSequence++;
|
||||
dev->checkpointCurrentChunk++;
|
||||
if(dev->checkpointCurrentChunk >= dev->nChunksPerBlock){
|
||||
if (dev->checkpointCurrentChunk >= dev->nChunksPerBlock) {
|
||||
dev->checkpointCurrentChunk = 0;
|
||||
dev->checkpointCurrentBlock = -1;
|
||||
}
|
||||
memset(dev->checkpointBuffer,0,dev->nDataBytesPerChunk);
|
||||
memset(dev->checkpointBuffer, 0, dev->nDataBytesPerChunk);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int yaffs_CheckpointWrite(yaffs_Device *dev,const void *data, int nBytes)
|
||||
int yaffs_CheckpointWrite(yaffs_Device *dev, const void *data, int nBytes)
|
||||
{
|
||||
int i=0;
|
||||
int i = 0;
|
||||
int ok = 1;
|
||||
|
||||
|
||||
|
@ -250,17 +244,14 @@ int yaffs_CheckpointWrite(yaffs_Device *dev,const void *data, int nBytes)
|
|||
|
||||
|
||||
|
||||
if(!dev->checkpointBuffer)
|
||||
if (!dev->checkpointBuffer)
|
||||
return 0;
|
||||
|
||||
if(!dev->checkpointOpenForWrite)
|
||||
if (!dev->checkpointOpenForWrite)
|
||||
return -1;
|
||||
|
||||
while(i < nBytes && ok) {
|
||||
|
||||
|
||||
|
||||
dev->checkpointBuffer[dev->checkpointByteOffset] = *dataBytes ;
|
||||
while (i < nBytes && ok) {
|
||||
dev->checkpointBuffer[dev->checkpointByteOffset] = *dataBytes;
|
||||
dev->checkpointSum += *dataBytes;
|
||||
dev->checkpointXor ^= *dataBytes;
|
||||
|
||||
|
@ -270,18 +261,17 @@ int yaffs_CheckpointWrite(yaffs_Device *dev,const void *data, int nBytes)
|
|||
dev->checkpointByteCount++;
|
||||
|
||||
|
||||
if(dev->checkpointByteOffset < 0 ||
|
||||
if (dev->checkpointByteOffset < 0 ||
|
||||
dev->checkpointByteOffset >= dev->nDataBytesPerChunk)
|
||||
ok = yaffs_CheckpointFlushBuffer(dev);
|
||||
|
||||
}
|
||||
|
||||
return i;
|
||||
return i;
|
||||
}
|
||||
|
||||
int yaffs_CheckpointRead(yaffs_Device *dev, void *data, int nBytes)
|
||||
{
|
||||
int i=0;
|
||||
int i = 0;
|
||||
int ok = 1;
|
||||
yaffs_ExtendedTags tags;
|
||||
|
||||
|
@ -291,52 +281,54 @@ int yaffs_CheckpointRead(yaffs_Device *dev, void *data, int nBytes)
|
|||
|
||||
__u8 *dataBytes = (__u8 *)data;
|
||||
|
||||
if(!dev->checkpointBuffer)
|
||||
if (!dev->checkpointBuffer)
|
||||
return 0;
|
||||
|
||||
if(dev->checkpointOpenForWrite)
|
||||
if (dev->checkpointOpenForWrite)
|
||||
return -1;
|
||||
|
||||
while(i < nBytes && ok) {
|
||||
while (i < nBytes && ok) {
|
||||
|
||||
|
||||
if(dev->checkpointByteOffset < 0 ||
|
||||
dev->checkpointByteOffset >= dev->nDataBytesPerChunk) {
|
||||
if (dev->checkpointByteOffset < 0 ||
|
||||
dev->checkpointByteOffset >= dev->nDataBytesPerChunk) {
|
||||
|
||||
if(dev->checkpointCurrentBlock < 0){
|
||||
if (dev->checkpointCurrentBlock < 0) {
|
||||
yaffs_CheckpointFindNextCheckpointBlock(dev);
|
||||
dev->checkpointCurrentChunk = 0;
|
||||
}
|
||||
|
||||
if(dev->checkpointCurrentBlock < 0)
|
||||
if (dev->checkpointCurrentBlock < 0)
|
||||
ok = 0;
|
||||
else {
|
||||
|
||||
chunk = dev->checkpointCurrentBlock * dev->nChunksPerBlock +
|
||||
dev->checkpointCurrentChunk;
|
||||
chunk = dev->checkpointCurrentBlock *
|
||||
dev->nChunksPerBlock +
|
||||
dev->checkpointCurrentChunk;
|
||||
|
||||
realignedChunk = chunk - dev->chunkOffset;
|
||||
|
||||
/* read in the next chunk */
|
||||
/* printf("read checkpoint page %d\n",dev->checkpointPage); */
|
||||
dev->readChunkWithTagsFromNAND(dev, realignedChunk,
|
||||
dev->checkpointBuffer,
|
||||
&tags);
|
||||
/* read in the next chunk */
|
||||
/* printf("read checkpoint page %d\n",dev->checkpointPage); */
|
||||
dev->readChunkWithTagsFromNAND(dev,
|
||||
realignedChunk,
|
||||
dev->checkpointBuffer,
|
||||
&tags);
|
||||
|
||||
if(tags.chunkId != (dev->checkpointPageSequence + 1) ||
|
||||
tags.sequenceNumber != YAFFS_SEQUENCE_CHECKPOINT_DATA)
|
||||
ok = 0;
|
||||
if (tags.chunkId != (dev->checkpointPageSequence + 1) ||
|
||||
tags.eccResult > YAFFS_ECC_RESULT_FIXED ||
|
||||
tags.sequenceNumber != YAFFS_SEQUENCE_CHECKPOINT_DATA)
|
||||
ok = 0;
|
||||
|
||||
dev->checkpointByteOffset = 0;
|
||||
dev->checkpointPageSequence++;
|
||||
dev->checkpointCurrentChunk++;
|
||||
|
||||
if(dev->checkpointCurrentChunk >= dev->nChunksPerBlock)
|
||||
if (dev->checkpointCurrentChunk >= dev->nChunksPerBlock)
|
||||
dev->checkpointCurrentBlock = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if(ok){
|
||||
if (ok) {
|
||||
*dataBytes = dev->checkpointBuffer[dev->checkpointByteOffset];
|
||||
dev->checkpointSum += *dataBytes;
|
||||
dev->checkpointXor ^= *dataBytes;
|
||||
|
@ -353,17 +345,17 @@ int yaffs_CheckpointRead(yaffs_Device *dev, void *data, int nBytes)
|
|||
int yaffs_CheckpointClose(yaffs_Device *dev)
|
||||
{
|
||||
|
||||
if(dev->checkpointOpenForWrite){
|
||||
if(dev->checkpointByteOffset != 0)
|
||||
if (dev->checkpointOpenForWrite) {
|
||||
if (dev->checkpointByteOffset != 0)
|
||||
yaffs_CheckpointFlushBuffer(dev);
|
||||
} else {
|
||||
int i;
|
||||
for(i = 0; i < dev->blocksInCheckpoint && dev->checkpointBlockList[i] >= 0; i++){
|
||||
yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,dev->checkpointBlockList[i]);
|
||||
if(bi->blockState == YAFFS_BLOCK_STATE_EMPTY)
|
||||
for (i = 0; i < dev->blocksInCheckpoint && dev->checkpointBlockList[i] >= 0; i++) {
|
||||
yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, dev->checkpointBlockList[i]);
|
||||
if (bi->blockState == YAFFS_BLOCK_STATE_EMPTY)
|
||||
bi->blockState = YAFFS_BLOCK_STATE_CHECKPOINT;
|
||||
else {
|
||||
// Todo this looks odd...
|
||||
/* Todo this looks odd... */
|
||||
}
|
||||
}
|
||||
YFREE(dev->checkpointBlockList);
|
||||
|
@ -374,27 +366,25 @@ int yaffs_CheckpointClose(yaffs_Device *dev)
|
|||
dev->nErasedBlocks -= dev->blocksInCheckpoint;
|
||||
|
||||
|
||||
T(YAFFS_TRACE_CHECKPOINT,(TSTR("checkpoint byte count %d" TENDSTR),
|
||||
T(YAFFS_TRACE_CHECKPOINT, (TSTR("checkpoint byte count %d" TENDSTR),
|
||||
dev->checkpointByteCount));
|
||||
|
||||
if(dev->checkpointBuffer){
|
||||
if (dev->checkpointBuffer) {
|
||||
/* free the buffer */
|
||||
YFREE(dev->checkpointBuffer);
|
||||
dev->checkpointBuffer = NULL;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
} else
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int yaffs_CheckpointInvalidateStream(yaffs_Device *dev)
|
||||
{
|
||||
/* Erase the first checksum block */
|
||||
|
||||
T(YAFFS_TRACE_CHECKPOINT,(TSTR("checkpoint invalidate"TENDSTR)));
|
||||
T(YAFFS_TRACE_CHECKPOINT, (TSTR("checkpoint invalidate"TENDSTR)));
|
||||
|
||||
if(!yaffs_CheckpointSpaceOk(dev))
|
||||
if (!yaffs_CheckpointSpaceOk(dev))
|
||||
return 0;
|
||||
|
||||
return yaffs_CheckpointErase(dev);
|
||||
|
|
|
@ -20,9 +20,9 @@
|
|||
|
||||
int yaffs_CheckpointOpen(yaffs_Device *dev, int forWriting);
|
||||
|
||||
int yaffs_CheckpointWrite(yaffs_Device *dev,const void *data, int nBytes);
|
||||
int yaffs_CheckpointWrite(yaffs_Device *dev, const void *data, int nBytes);
|
||||
|
||||
int yaffs_CheckpointRead(yaffs_Device *dev,void *data, int nBytes);
|
||||
int yaffs_CheckpointRead(yaffs_Device *dev, void *data, int nBytes);
|
||||
|
||||
int yaffs_GetCheckpointSum(yaffs_Device *dev, __u32 *sum);
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
*/
|
||||
|
||||
const char *yaffs_ecc_c_version =
|
||||
"$Id: yaffs_ecc.c,v 1.9 2007-02-14 01:09:06 wookey Exp $";
|
||||
"$Id: yaffs_ecc.c,v 1.11 2009-03-06 17:20:50 wookey Exp $";
|
||||
|
||||
#include "yportenv.h"
|
||||
|
||||
|
@ -109,12 +109,10 @@ void yaffs_ECCCalculate(const unsigned char *data, unsigned char *ecc)
|
|||
b = column_parity_table[*data++];
|
||||
col_parity ^= b;
|
||||
|
||||
if (b & 0x01) // odd number of bits in the byte
|
||||
{
|
||||
if (b & 0x01) { /* odd number of bits in the byte */
|
||||
line_parity ^= i;
|
||||
line_parity_prime ^= ~i;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ecc[2] = (~col_parity) | 0x03;
|
||||
|
@ -158,7 +156,7 @@ void yaffs_ECCCalculate(const unsigned char *data, unsigned char *ecc)
|
|||
ecc[0] = ~t;
|
||||
|
||||
#ifdef CONFIG_YAFFS_ECC_WRONG_ORDER
|
||||
// Swap the bytes into the wrong order
|
||||
/* Swap the bytes into the wrong order */
|
||||
t = ecc[0];
|
||||
ecc[0] = ecc[1];
|
||||
ecc[1] = t;
|
||||
|
@ -189,7 +187,7 @@ int yaffs_ECCCorrect(unsigned char *data, unsigned char *read_ecc,
|
|||
unsigned bit;
|
||||
|
||||
#ifdef CONFIG_YAFFS_ECC_WRONG_ORDER
|
||||
// swap the bytes to correct for the wrong order
|
||||
/* swap the bytes to correct for the wrong order */
|
||||
unsigned char t;
|
||||
|
||||
t = d0;
|
||||
|
@ -251,7 +249,7 @@ int yaffs_ECCCorrect(unsigned char *data, unsigned char *read_ecc,
|
|||
* ECCxxxOther does ECC calcs on arbitrary n bytes of data
|
||||
*/
|
||||
void yaffs_ECCCalculateOther(const unsigned char *data, unsigned nBytes,
|
||||
yaffs_ECCOther * eccOther)
|
||||
yaffs_ECCOther *eccOther)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
|
@ -278,8 +276,8 @@ void yaffs_ECCCalculateOther(const unsigned char *data, unsigned nBytes,
|
|||
}
|
||||
|
||||
int yaffs_ECCCorrectOther(unsigned char *data, unsigned nBytes,
|
||||
yaffs_ECCOther * read_ecc,
|
||||
const yaffs_ECCOther * test_ecc)
|
||||
yaffs_ECCOther *read_ecc,
|
||||
const yaffs_ECCOther *test_ecc)
|
||||
{
|
||||
unsigned char cDelta; /* column parity delta */
|
||||
unsigned lDelta; /* line parity delta */
|
||||
|
@ -294,8 +292,7 @@ int yaffs_ECCCorrectOther(unsigned char *data, unsigned nBytes,
|
|||
return 0; /* no error */
|
||||
|
||||
if (lDelta == ~lDeltaPrime &&
|
||||
(((cDelta ^ (cDelta >> 1)) & 0x15) == 0x15))
|
||||
{
|
||||
(((cDelta ^ (cDelta >> 1)) & 0x15) == 0x15)) {
|
||||
/* Single bit (recoverable) error in data */
|
||||
|
||||
bit = 0;
|
||||
|
@ -307,7 +304,7 @@ int yaffs_ECCCorrectOther(unsigned char *data, unsigned nBytes,
|
|||
if (cDelta & 0x02)
|
||||
bit |= 0x01;
|
||||
|
||||
if(lDelta >= nBytes)
|
||||
if (lDelta >= nBytes)
|
||||
return -1;
|
||||
|
||||
data[lDelta] ^= (1 << bit);
|
||||
|
@ -316,7 +313,7 @@ int yaffs_ECCCorrectOther(unsigned char *data, unsigned nBytes,
|
|||
}
|
||||
|
||||
if ((yaffs_CountBits32(lDelta) + yaffs_CountBits32(lDeltaPrime) +
|
||||
yaffs_CountBits(cDelta)) == 1) {
|
||||
yaffs_CountBits(cDelta)) == 1) {
|
||||
/* Reccoverable error in ecc */
|
||||
|
||||
*read_ecc = *test_ecc;
|
||||
|
@ -326,6 +323,4 @@ int yaffs_ECCCorrectOther(unsigned char *data, unsigned nBytes,
|
|||
/* Unrecoverable error */
|
||||
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -13,15 +13,15 @@
|
|||
* Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code implements the ECC algorithm used in SmartMedia.
|
||||
*
|
||||
* The ECC comprises 22 bits of parity information and is stuffed into 3 bytes.
|
||||
* The two unused bit are set to 1.
|
||||
* The ECC can correct single bit errors in a 256-byte page of data. Thus, two such ECC
|
||||
* blocks are used on a 512-byte NAND page.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* This code implements the ECC algorithm used in SmartMedia.
|
||||
*
|
||||
* The ECC comprises 22 bits of parity information and is stuffed into 3 bytes.
|
||||
* The two unused bit are set to 1.
|
||||
* The ECC can correct single bit errors in a 256-byte page of data. Thus, two such ECC
|
||||
* blocks are used on a 512-byte NAND page.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __YAFFS_ECC_H__
|
||||
#define __YAFFS_ECC_H__
|
||||
|
@ -34,11 +34,11 @@ typedef struct {
|
|||
|
||||
void yaffs_ECCCalculate(const unsigned char *data, unsigned char *ecc);
|
||||
int yaffs_ECCCorrect(unsigned char *data, unsigned char *read_ecc,
|
||||
const unsigned char *test_ecc);
|
||||
const unsigned char *test_ecc);
|
||||
|
||||
void yaffs_ECCCalculateOther(const unsigned char *data, unsigned nBytes,
|
||||
yaffs_ECCOther * ecc);
|
||||
yaffs_ECCOther *ecc);
|
||||
int yaffs_ECCCorrectOther(unsigned char *data, unsigned nBytes,
|
||||
yaffs_ECCOther * read_ecc,
|
||||
const yaffs_ECCOther * test_ecc);
|
||||
yaffs_ECCOther *read_ecc,
|
||||
const yaffs_ECCOther *test_ecc);
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load diff
34
target/linux/generic/files/fs/yaffs2/yaffs_getblockinfo.h
Normal file
34
target/linux/generic/files/fs/yaffs2/yaffs_getblockinfo.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
|
||||
*
|
||||
* Copyright (C) 2002-2007 Aleph One Ltd.
|
||||
* for Toby Churchill Ltd and Brightstar Engineering
|
||||
*
|
||||
* Created by Charles Manning <charles@aleph1.co.uk>
|
||||
*
|
||||
* 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_GETBLOCKINFO_H__
|
||||
#define __YAFFS_GETBLOCKINFO_H__
|
||||
|
||||
#include "yaffs_guts.h"
|
||||
|
||||
/* Function to manipulate block info */
|
||||
static Y_INLINE yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device * dev, int blk)
|
||||
{
|
||||
if (blk < dev->internalStartBlock || blk > dev->internalEndBlock) {
|
||||
T(YAFFS_TRACE_ERROR,
|
||||
(TSTR
|
||||
("**>> yaffs: getBlockInfo block %d is not valid" TENDSTR),
|
||||
blk));
|
||||
YBUG();
|
||||
}
|
||||
return &dev->blockInfo[blk - dev->internalStartBlock];
|
||||
}
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load diff
|
@ -90,7 +90,7 @@
|
|||
|
||||
#define YAFFS_MAX_SHORT_OP_CACHES 20
|
||||
|
||||
#define YAFFS_N_TEMP_BUFFERS 4
|
||||
#define YAFFS_N_TEMP_BUFFERS 6
|
||||
|
||||
/* We limit the number attempts at sucessfully saving a chunk of data.
|
||||
* Small-page devices have 32 pages per block; large-page devices have 64.
|
||||
|
@ -108,6 +108,9 @@
|
|||
#define YAFFS_LOWEST_SEQUENCE_NUMBER 0x00001000
|
||||
#define YAFFS_HIGHEST_SEQUENCE_NUMBER 0xEFFFFF00
|
||||
|
||||
/* Special sequence number for bad block that failed to be marked bad */
|
||||
#define YAFFS_SEQUENCE_BAD_BLOCK 0xFFFF0000
|
||||
|
||||
/* ChunkCache is used for short read/write operations.*/
|
||||
typedef struct {
|
||||
struct yaffs_ObjectStruct *object;
|
||||
|
@ -134,11 +137,10 @@ typedef struct {
|
|||
typedef struct {
|
||||
unsigned chunkId:20;
|
||||
unsigned serialNumber:2;
|
||||
unsigned byteCount:10;
|
||||
unsigned byteCountLSB:10;
|
||||
unsigned objectId:18;
|
||||
unsigned ecc:12;
|
||||
unsigned unusedStuff:2;
|
||||
|
||||
unsigned byteCountMSB:2;
|
||||
} yaffs_Tags;
|
||||
|
||||
typedef union {
|
||||
|
@ -277,13 +279,13 @@ typedef struct {
|
|||
|
||||
int softDeletions:10; /* number of soft deleted pages */
|
||||
int pagesInUse:10; /* number of pages in use */
|
||||
yaffs_BlockState blockState:4; /* One of the above block states */
|
||||
unsigned blockState:4; /* One of the above block states. NB use unsigned because enum is sometimes an int */
|
||||
__u32 needsRetiring:1; /* Data has failed on this block, need to get valid data off */
|
||||
/* and retire the block. */
|
||||
__u32 skipErasedCheck: 1; /* If this is set we can skip the erased check on this block */
|
||||
__u32 gcPrioritise: 1; /* An ECC check or blank check has failed on this block.
|
||||
/* and retire the block. */
|
||||
__u32 skipErasedCheck:1; /* If this is set we can skip the erased check on this block */
|
||||
__u32 gcPrioritise:1; /* An ECC check or blank check has failed on this block.
|
||||
It should be prioritised for GC */
|
||||
__u32 chunkErrorStrikes:3; /* How many times we've had ecc etc failures on this block and tried to reuse it */
|
||||
__u32 chunkErrorStrikes:3; /* How many times we've had ecc etc failures on this block and tried to reuse it */
|
||||
|
||||
#ifdef CONFIG_YAFFS_YAFFS2
|
||||
__u32 hasShrinkHeader:1; /* This block has at least one shrink object header */
|
||||
|
@ -300,11 +302,11 @@ typedef struct {
|
|||
|
||||
/* Apply to everything */
|
||||
int parentObjectId;
|
||||
__u16 sum__NoLongerUsed; /* checksum of name. No longer used */
|
||||
__u16 sum__NoLongerUsed; /* checksum of name. No longer used */
|
||||
YCHAR name[YAFFS_MAX_NAME_LENGTH + 1];
|
||||
|
||||
/* Thes following apply to directories, files, symlinks - not hard links */
|
||||
__u32 yst_mode; /* protection */
|
||||
/* The following apply to directories, files, symlinks - not hard links */
|
||||
__u32 yst_mode; /* protection */
|
||||
|
||||
#ifdef CONFIG_YAFFS_WINCE
|
||||
__u32 notForWinCE[5];
|
||||
|
@ -331,11 +333,14 @@ typedef struct {
|
|||
__u32 win_ctime[2];
|
||||
__u32 win_atime[2];
|
||||
__u32 win_mtime[2];
|
||||
__u32 roomToGrow[4];
|
||||
#else
|
||||
__u32 roomToGrow[10];
|
||||
#endif
|
||||
__u32 roomToGrow[6];
|
||||
|
||||
#endif
|
||||
__u32 inbandShadowsObject;
|
||||
__u32 inbandIsShrink;
|
||||
|
||||
__u32 reservedSpace[2];
|
||||
int shadowsObject; /* This object header shadows the specified object if > 0 */
|
||||
|
||||
/* isShrink applies to object headers written when we shrink the file (ie resize) */
|
||||
|
@ -381,7 +386,7 @@ typedef struct {
|
|||
} yaffs_FileStructure;
|
||||
|
||||
typedef struct {
|
||||
struct list_head children; /* list of child links */
|
||||
struct ylist_head children; /* list of child links */
|
||||
} yaffs_DirectoryStructure;
|
||||
|
||||
typedef struct {
|
||||
|
@ -418,23 +423,24 @@ struct yaffs_ObjectStruct {
|
|||
* still in the inode cache. Free of object is defered.
|
||||
* until the inode is released.
|
||||
*/
|
||||
__u8 beingCreated:1; /* This object is still being created so skip some checks. */
|
||||
|
||||
__u8 serial; /* serial number of chunk in NAND. Cached here */
|
||||
__u16 sum; /* sum of the name to speed searching */
|
||||
|
||||
struct yaffs_DeviceStruct *myDev; /* The device I'm on */
|
||||
struct yaffs_DeviceStruct *myDev; /* The device I'm on */
|
||||
|
||||
struct list_head hashLink; /* list of objects in this hash bucket */
|
||||
struct ylist_head hashLink; /* list of objects in this hash bucket */
|
||||
|
||||
struct list_head hardLinks; /* all the equivalent hard linked objects */
|
||||
struct ylist_head hardLinks; /* all the equivalent hard linked objects */
|
||||
|
||||
/* directory structure stuff */
|
||||
/* also used for linking up the free list */
|
||||
struct yaffs_ObjectStruct *parent;
|
||||
struct list_head siblings;
|
||||
struct ylist_head siblings;
|
||||
|
||||
/* Where's my object header in NAND? */
|
||||
int chunkId;
|
||||
int hdrChunk;
|
||||
|
||||
int nDataChunks; /* Number of data chunks attached to the file. */
|
||||
|
||||
|
@ -485,7 +491,7 @@ struct yaffs_ObjectList_struct {
|
|||
typedef struct yaffs_ObjectList_struct yaffs_ObjectList;
|
||||
|
||||
typedef struct {
|
||||
struct list_head list;
|
||||
struct ylist_head list;
|
||||
int count;
|
||||
} yaffs_ObjectBucket;
|
||||
|
||||
|
@ -495,11 +501,10 @@ typedef struct {
|
|||
*/
|
||||
|
||||
typedef struct {
|
||||
int structType;
|
||||
int structType;
|
||||
__u32 objectId;
|
||||
__u32 parentId;
|
||||
int chunkId;
|
||||
|
||||
int hdrChunk;
|
||||
yaffs_ObjectType variantType:3;
|
||||
__u8 deleted:1;
|
||||
__u8 softDeleted:1;
|
||||
|
@ -511,8 +516,7 @@ typedef struct {
|
|||
|
||||
int nDataChunks;
|
||||
__u32 fileSizeOrEquivalentObjectId;
|
||||
|
||||
}yaffs_CheckpointObject;
|
||||
} yaffs_CheckpointObject;
|
||||
|
||||
/*--------------------- Temporary buffers ----------------
|
||||
*
|
||||
|
@ -528,13 +532,13 @@ typedef struct {
|
|||
/*----------------- Device ---------------------------------*/
|
||||
|
||||
struct yaffs_DeviceStruct {
|
||||
struct list_head devList;
|
||||
struct ylist_head devList;
|
||||
const char *name;
|
||||
|
||||
/* Entry parameters set up way early. Yaffs sets up the rest.*/
|
||||
int nDataBytesPerChunk; /* Should be a power of 2 >= 512 */
|
||||
int nChunksPerBlock; /* does not need to be a power of 2 */
|
||||
int nBytesPerSpare; /* spare area size */
|
||||
int spareBytesPerChunk; /* spare area size */
|
||||
int startBlock; /* Start block we're allowed to use */
|
||||
int endBlock; /* End block we're allowed to use */
|
||||
int nReservedBlocks; /* We want this tuneable so that we can reduce */
|
||||
|
@ -544,9 +548,7 @@ struct yaffs_DeviceStruct {
|
|||
/* Stuff used by the shared space checkpointing mechanism */
|
||||
/* If this value is zero, then this mechanism is disabled */
|
||||
|
||||
int nCheckpointReservedBlocks; /* Blocks to reserve for checkpoint data */
|
||||
|
||||
|
||||
/* int nCheckpointReservedBlocks; */ /* Blocks to reserve for checkpoint data */
|
||||
|
||||
|
||||
int nShortOpCaches; /* If <= 0, then short op caching is disabled, else
|
||||
|
@ -560,30 +562,31 @@ struct yaffs_DeviceStruct {
|
|||
void *genericDevice; /* Pointer to device context
|
||||
* On an mtd this holds the mtd pointer.
|
||||
*/
|
||||
void *superBlock;
|
||||
void *superBlock;
|
||||
|
||||
/* NAND access functions (Must be set before calling YAFFS)*/
|
||||
|
||||
int (*writeChunkToNAND) (struct yaffs_DeviceStruct * dev,
|
||||
int chunkInNAND, const __u8 * data,
|
||||
const yaffs_Spare * spare);
|
||||
int (*readChunkFromNAND) (struct yaffs_DeviceStruct * dev,
|
||||
int chunkInNAND, __u8 * data,
|
||||
yaffs_Spare * spare);
|
||||
int (*eraseBlockInNAND) (struct yaffs_DeviceStruct * dev,
|
||||
int blockInNAND);
|
||||
int (*initialiseNAND) (struct yaffs_DeviceStruct * dev);
|
||||
int (*writeChunkToNAND) (struct yaffs_DeviceStruct *dev,
|
||||
int chunkInNAND, const __u8 *data,
|
||||
const yaffs_Spare *spare);
|
||||
int (*readChunkFromNAND) (struct yaffs_DeviceStruct *dev,
|
||||
int chunkInNAND, __u8 *data,
|
||||
yaffs_Spare *spare);
|
||||
int (*eraseBlockInNAND) (struct yaffs_DeviceStruct *dev,
|
||||
int blockInNAND);
|
||||
int (*initialiseNAND) (struct yaffs_DeviceStruct *dev);
|
||||
int (*deinitialiseNAND) (struct yaffs_DeviceStruct *dev);
|
||||
|
||||
#ifdef CONFIG_YAFFS_YAFFS2
|
||||
int (*writeChunkWithTagsToNAND) (struct yaffs_DeviceStruct * dev,
|
||||
int chunkInNAND, const __u8 * data,
|
||||
const yaffs_ExtendedTags * tags);
|
||||
int (*readChunkWithTagsFromNAND) (struct yaffs_DeviceStruct * dev,
|
||||
int chunkInNAND, __u8 * data,
|
||||
yaffs_ExtendedTags * tags);
|
||||
int (*markNANDBlockBad) (struct yaffs_DeviceStruct * dev, int blockNo);
|
||||
int (*queryNANDBlock) (struct yaffs_DeviceStruct * dev, int blockNo,
|
||||
yaffs_BlockState * state, int *sequenceNumber);
|
||||
int (*writeChunkWithTagsToNAND) (struct yaffs_DeviceStruct *dev,
|
||||
int chunkInNAND, const __u8 *data,
|
||||
const yaffs_ExtendedTags *tags);
|
||||
int (*readChunkWithTagsFromNAND) (struct yaffs_DeviceStruct *dev,
|
||||
int chunkInNAND, __u8 *data,
|
||||
yaffs_ExtendedTags *tags);
|
||||
int (*markNANDBlockBad) (struct yaffs_DeviceStruct *dev, int blockNo);
|
||||
int (*queryNANDBlock) (struct yaffs_DeviceStruct *dev, int blockNo,
|
||||
yaffs_BlockState *state, __u32 *sequenceNumber);
|
||||
#endif
|
||||
|
||||
int isYaffs2;
|
||||
|
@ -595,10 +598,12 @@ struct yaffs_DeviceStruct {
|
|||
void (*removeObjectCallback)(struct yaffs_ObjectStruct *obj);
|
||||
|
||||
/* Callback to mark the superblock dirsty */
|
||||
void (*markSuperBlockDirty)(void * superblock);
|
||||
void (*markSuperBlockDirty)(void *superblock);
|
||||
|
||||
int wideTnodesDisabled; /* Set to disable wide tnodes */
|
||||
|
||||
YCHAR *pathDividers; /* String of legal path dividers */
|
||||
|
||||
|
||||
/* End of stuff that must be set before initialisation. */
|
||||
|
||||
|
@ -615,16 +620,14 @@ struct yaffs_DeviceStruct {
|
|||
__u32 tnodeWidth;
|
||||
__u32 tnodeMask;
|
||||
|
||||
/* Stuff to support various file offses to chunk/offset translations */
|
||||
/* "Crumbs" for nDataBytesPerChunk not being a power of 2 */
|
||||
__u32 crumbMask;
|
||||
__u32 crumbShift;
|
||||
__u32 crumbsPerChunk;
|
||||
|
||||
/* Straight shifting for nDataBytesPerChunk being a power of 2 */
|
||||
__u32 chunkShift;
|
||||
__u32 chunkMask;
|
||||
/* Stuff for figuring out file offset to chunk conversions */
|
||||
__u32 chunkShift; /* Shift value */
|
||||
__u32 chunkDiv; /* Divisor after shifting: 1 for power-of-2 sizes */
|
||||
__u32 chunkMask; /* Mask to use for power-of-2 case */
|
||||
|
||||
/* Stuff to handle inband tags */
|
||||
int inbandTags;
|
||||
__u32 totalBytesPerChunk;
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
|
@ -633,7 +636,7 @@ struct yaffs_DeviceStruct {
|
|||
__u8 *spareBuffer; /* For mtdif2 use. Don't know the size of the buffer
|
||||
* at compile time so we have to allocate it.
|
||||
*/
|
||||
void (*putSuperFunc) (struct super_block * sb);
|
||||
void (*putSuperFunc) (struct super_block *sb);
|
||||
#endif
|
||||
|
||||
int isMounted;
|
||||
|
@ -663,6 +666,8 @@ struct yaffs_DeviceStruct {
|
|||
__u32 checkpointSum;
|
||||
__u32 checkpointXor;
|
||||
|
||||
int nCheckpointBlocksRequired; /* Number of blocks needed to store current checkpoint set */
|
||||
|
||||
/* Block Info */
|
||||
yaffs_BlockInfo *blockInfo;
|
||||
__u8 *chunkBits; /* bitmap of chunks in use */
|
||||
|
@ -684,11 +689,15 @@ struct yaffs_DeviceStruct {
|
|||
yaffs_TnodeList *allocatedTnodeList;
|
||||
|
||||
int isDoingGC;
|
||||
int gcBlock;
|
||||
int gcChunk;
|
||||
|
||||
int nObjectsCreated;
|
||||
yaffs_Object *freeObjects;
|
||||
int nFreeObjects;
|
||||
|
||||
int nHardLinks;
|
||||
|
||||
yaffs_ObjectList *allocatedObjectList;
|
||||
|
||||
yaffs_ObjectBucket objectBucket[YAFFS_NOBJECT_BUCKETS];
|
||||
|
@ -745,8 +754,10 @@ struct yaffs_DeviceStruct {
|
|||
int nBackgroundDeletions; /* Count of background deletions. */
|
||||
|
||||
|
||||
/* Temporary buffer management */
|
||||
yaffs_TempBuffer tempBuffer[YAFFS_N_TEMP_BUFFERS];
|
||||
int maxTemp;
|
||||
int tempInUse;
|
||||
int unmanagedTempAllocations;
|
||||
int unmanagedTempDeallocations;
|
||||
|
||||
|
@ -758,9 +769,9 @@ struct yaffs_DeviceStruct {
|
|||
|
||||
typedef struct yaffs_DeviceStruct yaffs_Device;
|
||||
|
||||
/* The static layout of bllock usage etc is stored in the super block header */
|
||||
/* The static layout of block usage etc is stored in the super block header */
|
||||
typedef struct {
|
||||
int StructType;
|
||||
int StructType;
|
||||
int version;
|
||||
int checkpointStartBlock;
|
||||
int checkpointEndBlock;
|
||||
|
@ -773,7 +784,7 @@ typedef struct {
|
|||
* must be preserved over unmount/mount cycles.
|
||||
*/
|
||||
typedef struct {
|
||||
int structType;
|
||||
int structType;
|
||||
int nErasedBlocks;
|
||||
int allocationBlock; /* Current block being allocated off */
|
||||
__u32 allocationPage;
|
||||
|
@ -791,57 +802,45 @@ typedef struct {
|
|||
|
||||
|
||||
typedef struct {
|
||||
int structType;
|
||||
__u32 magic;
|
||||
__u32 version;
|
||||
__u32 head;
|
||||
int structType;
|
||||
__u32 magic;
|
||||
__u32 version;
|
||||
__u32 head;
|
||||
} yaffs_CheckpointValidity;
|
||||
|
||||
/* Function to manipulate block info */
|
||||
static Y_INLINE yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device * dev, int blk)
|
||||
{
|
||||
if (blk < dev->internalStartBlock || blk > dev->internalEndBlock) {
|
||||
T(YAFFS_TRACE_ERROR,
|
||||
(TSTR
|
||||
("**>> yaffs: getBlockInfo block %d is not valid" TENDSTR),
|
||||
blk));
|
||||
YBUG();
|
||||
}
|
||||
return &dev->blockInfo[blk - dev->internalStartBlock];
|
||||
}
|
||||
|
||||
/*----------------------- YAFFS Functions -----------------------*/
|
||||
|
||||
int yaffs_GutsInitialise(yaffs_Device * dev);
|
||||
void yaffs_Deinitialise(yaffs_Device * dev);
|
||||
int yaffs_GutsInitialise(yaffs_Device *dev);
|
||||
void yaffs_Deinitialise(yaffs_Device *dev);
|
||||
|
||||
int yaffs_GetNumberOfFreeChunks(yaffs_Device * dev);
|
||||
int yaffs_GetNumberOfFreeChunks(yaffs_Device *dev);
|
||||
|
||||
int yaffs_RenameObject(yaffs_Object * oldDir, const YCHAR * oldName,
|
||||
yaffs_Object * newDir, const YCHAR * newName);
|
||||
int yaffs_RenameObject(yaffs_Object *oldDir, const YCHAR *oldName,
|
||||
yaffs_Object *newDir, const YCHAR *newName);
|
||||
|
||||
int yaffs_Unlink(yaffs_Object * dir, const YCHAR * name);
|
||||
int yaffs_DeleteFile(yaffs_Object * obj);
|
||||
int yaffs_Unlink(yaffs_Object *dir, const YCHAR *name);
|
||||
int yaffs_DeleteObject(yaffs_Object *obj);
|
||||
|
||||
int yaffs_GetObjectName(yaffs_Object * obj, YCHAR * name, int buffSize);
|
||||
int yaffs_GetObjectFileLength(yaffs_Object * obj);
|
||||
int yaffs_GetObjectInode(yaffs_Object * obj);
|
||||
unsigned yaffs_GetObjectType(yaffs_Object * obj);
|
||||
int yaffs_GetObjectLinkCount(yaffs_Object * obj);
|
||||
int yaffs_GetObjectName(yaffs_Object *obj, YCHAR *name, int buffSize);
|
||||
int yaffs_GetObjectFileLength(yaffs_Object *obj);
|
||||
int yaffs_GetObjectInode(yaffs_Object *obj);
|
||||
unsigned yaffs_GetObjectType(yaffs_Object *obj);
|
||||
int yaffs_GetObjectLinkCount(yaffs_Object *obj);
|
||||
|
||||
int yaffs_SetAttributes(yaffs_Object * obj, struct iattr *attr);
|
||||
int yaffs_GetAttributes(yaffs_Object * obj, struct iattr *attr);
|
||||
int yaffs_SetAttributes(yaffs_Object *obj, struct iattr *attr);
|
||||
int yaffs_GetAttributes(yaffs_Object *obj, struct iattr *attr);
|
||||
|
||||
/* File operations */
|
||||
int yaffs_ReadDataFromFile(yaffs_Object * obj, __u8 * buffer, loff_t offset,
|
||||
int nBytes);
|
||||
int yaffs_WriteDataToFile(yaffs_Object * obj, const __u8 * buffer, loff_t offset,
|
||||
int nBytes, int writeThrough);
|
||||
int yaffs_ResizeFile(yaffs_Object * obj, loff_t newSize);
|
||||
int yaffs_ReadDataFromFile(yaffs_Object *obj, __u8 *buffer, loff_t offset,
|
||||
int nBytes);
|
||||
int yaffs_WriteDataToFile(yaffs_Object *obj, const __u8 *buffer, loff_t offset,
|
||||
int nBytes, int writeThrough);
|
||||
int yaffs_ResizeFile(yaffs_Object *obj, loff_t newSize);
|
||||
|
||||
yaffs_Object *yaffs_MknodFile(yaffs_Object * parent, const YCHAR * name,
|
||||
__u32 mode, __u32 uid, __u32 gid);
|
||||
int yaffs_FlushFile(yaffs_Object * obj, int updateTime);
|
||||
yaffs_Object *yaffs_MknodFile(yaffs_Object *parent, const YCHAR *name,
|
||||
__u32 mode, __u32 uid, __u32 gid);
|
||||
int yaffs_FlushFile(yaffs_Object *obj, int updateTime);
|
||||
|
||||
/* Flushing and checkpointing */
|
||||
void yaffs_FlushEntireDeviceCache(yaffs_Device *dev);
|
||||
|
@ -850,33 +849,33 @@ int yaffs_CheckpointSave(yaffs_Device *dev);
|
|||
int yaffs_CheckpointRestore(yaffs_Device *dev);
|
||||
|
||||
/* Directory operations */
|
||||
yaffs_Object *yaffs_MknodDirectory(yaffs_Object * parent, const YCHAR * name,
|
||||
__u32 mode, __u32 uid, __u32 gid);
|
||||
yaffs_Object *yaffs_FindObjectByName(yaffs_Object * theDir, const YCHAR * name);
|
||||
int yaffs_ApplyToDirectoryChildren(yaffs_Object * theDir,
|
||||
yaffs_Object *yaffs_MknodDirectory(yaffs_Object *parent, const YCHAR *name,
|
||||
__u32 mode, __u32 uid, __u32 gid);
|
||||
yaffs_Object *yaffs_FindObjectByName(yaffs_Object *theDir, const YCHAR *name);
|
||||
int yaffs_ApplyToDirectoryChildren(yaffs_Object *theDir,
|
||||
int (*fn) (yaffs_Object *));
|
||||
|
||||
yaffs_Object *yaffs_FindObjectByNumber(yaffs_Device * dev, __u32 number);
|
||||
yaffs_Object *yaffs_FindObjectByNumber(yaffs_Device *dev, __u32 number);
|
||||
|
||||
/* Link operations */
|
||||
yaffs_Object *yaffs_Link(yaffs_Object * parent, const YCHAR * name,
|
||||
yaffs_Object * equivalentObject);
|
||||
yaffs_Object *yaffs_Link(yaffs_Object *parent, const YCHAR *name,
|
||||
yaffs_Object *equivalentObject);
|
||||
|
||||
yaffs_Object *yaffs_GetEquivalentObject(yaffs_Object * obj);
|
||||
yaffs_Object *yaffs_GetEquivalentObject(yaffs_Object *obj);
|
||||
|
||||
/* Symlink operations */
|
||||
yaffs_Object *yaffs_MknodSymLink(yaffs_Object * parent, const YCHAR * name,
|
||||
yaffs_Object *yaffs_MknodSymLink(yaffs_Object *parent, const YCHAR *name,
|
||||
__u32 mode, __u32 uid, __u32 gid,
|
||||
const YCHAR * alias);
|
||||
YCHAR *yaffs_GetSymlinkAlias(yaffs_Object * obj);
|
||||
const YCHAR *alias);
|
||||
YCHAR *yaffs_GetSymlinkAlias(yaffs_Object *obj);
|
||||
|
||||
/* Special inodes (fifos, sockets and devices) */
|
||||
yaffs_Object *yaffs_MknodSpecial(yaffs_Object * parent, const YCHAR * name,
|
||||
yaffs_Object *yaffs_MknodSpecial(yaffs_Object *parent, const YCHAR *name,
|
||||
__u32 mode, __u32 uid, __u32 gid, __u32 rdev);
|
||||
|
||||
/* Special directories */
|
||||
yaffs_Object *yaffs_Root(yaffs_Device * dev);
|
||||
yaffs_Object *yaffs_LostNFound(yaffs_Device * dev);
|
||||
yaffs_Object *yaffs_Root(yaffs_Device *dev);
|
||||
yaffs_Object *yaffs_LostNFound(yaffs_Device *dev);
|
||||
|
||||
#ifdef CONFIG_YAFFS_WINCE
|
||||
/* CONFIG_YAFFS_WINCE special stuff */
|
||||
|
@ -885,18 +884,21 @@ void yfsd_WinFileTimeNow(__u32 target[2]);
|
|||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
void yaffs_HandleDeferedFree(yaffs_Object * obj);
|
||||
void yaffs_HandleDeferedFree(yaffs_Object *obj);
|
||||
#endif
|
||||
|
||||
/* Debug dump */
|
||||
int yaffs_DumpObject(yaffs_Object * obj);
|
||||
int yaffs_DumpObject(yaffs_Object *obj);
|
||||
|
||||
void yaffs_GutsTest(yaffs_Device * dev);
|
||||
void yaffs_GutsTest(yaffs_Device *dev);
|
||||
|
||||
/* A few useful functions */
|
||||
void yaffs_InitialiseTags(yaffs_ExtendedTags * tags);
|
||||
void yaffs_DeleteChunk(yaffs_Device * dev, int chunkId, int markNAND, int lyn);
|
||||
int yaffs_CheckFF(__u8 * buffer, int nBytes);
|
||||
void yaffs_InitialiseTags(yaffs_ExtendedTags *tags);
|
||||
void yaffs_DeleteChunk(yaffs_Device *dev, int chunkId, int markNAND, int lyn);
|
||||
int yaffs_CheckFF(__u8 *buffer, int nBytes);
|
||||
void yaffs_HandleChunkError(yaffs_Device *dev, yaffs_BlockInfo *bi);
|
||||
|
||||
__u8 *yaffs_GetTempBuffer(yaffs_Device *dev, int lineNo);
|
||||
void yaffs_ReleaseTempBuffer(yaffs_Device *dev, __u8 *buffer, int lineNo);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
*/
|
||||
|
||||
const char *yaffs_mtdif_c_version =
|
||||
"$Id: yaffs_mtdif.c,v 1.19 2007-02-14 01:09:06 wookey Exp $";
|
||||
"$Id: yaffs_mtdif.c,v 1.22 2009-03-06 17:20:51 wookey Exp $";
|
||||
|
||||
#include "yportenv.h"
|
||||
|
||||
|
@ -24,7 +24,7 @@ const char *yaffs_mtdif_c_version =
|
|||
#include "linux/time.h"
|
||||
#include "linux/mtd/nand.h"
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18))
|
||||
#if (MTD_VERSION_CODE < MTD_VERSION(2, 6, 18))
|
||||
static struct nand_oobinfo yaffs_oobinfo = {
|
||||
.useecc = 1,
|
||||
.eccbytes = 6,
|
||||
|
@ -36,7 +36,7 @@ static struct nand_oobinfo yaffs_noeccinfo = {
|
|||
};
|
||||
#endif
|
||||
|
||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
|
||||
#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17))
|
||||
static inline void translate_spare2oob(const yaffs_Spare *spare, __u8 *oob)
|
||||
{
|
||||
oob[0] = spare->tagByte0;
|
||||
|
@ -45,8 +45,8 @@ static inline void translate_spare2oob(const yaffs_Spare *spare, __u8 *oob)
|
|||
oob[3] = spare->tagByte3;
|
||||
oob[4] = spare->tagByte4;
|
||||
oob[5] = spare->tagByte5 & 0x3f;
|
||||
oob[5] |= spare->blockStatus == 'Y' ? 0: 0x80;
|
||||
oob[5] |= spare->pageStatus == 0 ? 0: 0x40;
|
||||
oob[5] |= spare->blockStatus == 'Y' ? 0 : 0x80;
|
||||
oob[5] |= spare->pageStatus == 0 ? 0 : 0x40;
|
||||
oob[6] = spare->tagByte6;
|
||||
oob[7] = spare->tagByte7;
|
||||
}
|
||||
|
@ -71,18 +71,18 @@ static inline void translate_oob2spare(yaffs_Spare *spare, __u8 *oob)
|
|||
}
|
||||
#endif
|
||||
|
||||
int nandmtd_WriteChunkToNAND(yaffs_Device * dev, int chunkInNAND,
|
||||
const __u8 * data, const yaffs_Spare * spare)
|
||||
int nandmtd_WriteChunkToNAND(yaffs_Device *dev, int chunkInNAND,
|
||||
const __u8 *data, const yaffs_Spare *spare)
|
||||
{
|
||||
struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
|
||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
|
||||
#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17))
|
||||
struct mtd_oob_ops ops;
|
||||
#endif
|
||||
size_t dummy;
|
||||
int retval = 0;
|
||||
|
||||
loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
|
||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
|
||||
#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17))
|
||||
__u8 spareAsBytes[8]; /* OOB */
|
||||
|
||||
if (data && !spare)
|
||||
|
@ -135,18 +135,18 @@ int nandmtd_WriteChunkToNAND(yaffs_Device * dev, int chunkInNAND,
|
|||
return YAFFS_FAIL;
|
||||
}
|
||||
|
||||
int nandmtd_ReadChunkFromNAND(yaffs_Device * dev, int chunkInNAND, __u8 * data,
|
||||
yaffs_Spare * spare)
|
||||
int nandmtd_ReadChunkFromNAND(yaffs_Device *dev, int chunkInNAND, __u8 *data,
|
||||
yaffs_Spare *spare)
|
||||
{
|
||||
struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
|
||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
|
||||
#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17))
|
||||
struct mtd_oob_ops ops;
|
||||
#endif
|
||||
size_t dummy;
|
||||
int retval = 0;
|
||||
|
||||
loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
|
||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
|
||||
#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17))
|
||||
__u8 spareAsBytes[8]; /* OOB */
|
||||
|
||||
if (data && !spare)
|
||||
|
@ -205,7 +205,7 @@ int nandmtd_ReadChunkFromNAND(yaffs_Device * dev, int chunkInNAND, __u8 * data,
|
|||
return YAFFS_FAIL;
|
||||
}
|
||||
|
||||
int nandmtd_EraseBlockInNAND(yaffs_Device * dev, int blockNumber)
|
||||
int nandmtd_EraseBlockInNAND(yaffs_Device *dev, int blockNumber)
|
||||
{
|
||||
struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
|
||||
__u32 addr =
|
||||
|
@ -234,7 +234,7 @@ int nandmtd_EraseBlockInNAND(yaffs_Device * dev, int blockNumber)
|
|||
return YAFFS_FAIL;
|
||||
}
|
||||
|
||||
int nandmtd_InitialiseNAND(yaffs_Device * dev)
|
||||
int nandmtd_InitialiseNAND(yaffs_Device *dev)
|
||||
{
|
||||
return YAFFS_OK;
|
||||
}
|
||||
|
|
|
@ -18,10 +18,15 @@
|
|||
|
||||
#include "yaffs_guts.h"
|
||||
|
||||
int nandmtd_WriteChunkToNAND(yaffs_Device * dev, int chunkInNAND,
|
||||
const __u8 * data, const yaffs_Spare * spare);
|
||||
int nandmtd_ReadChunkFromNAND(yaffs_Device * dev, int chunkInNAND, __u8 * data,
|
||||
yaffs_Spare * spare);
|
||||
int nandmtd_EraseBlockInNAND(yaffs_Device * dev, int blockNumber);
|
||||
int nandmtd_InitialiseNAND(yaffs_Device * dev);
|
||||
#if (MTD_VERSION_CODE < MTD_VERSION(2, 6, 18))
|
||||
extern struct nand_oobinfo yaffs_oobinfo;
|
||||
extern struct nand_oobinfo yaffs_noeccinfo;
|
||||
#endif
|
||||
|
||||
int nandmtd_WriteChunkToNAND(yaffs_Device *dev, int chunkInNAND,
|
||||
const __u8 *data, const yaffs_Spare *spare);
|
||||
int nandmtd_ReadChunkFromNAND(yaffs_Device *dev, int chunkInNAND, __u8 *data,
|
||||
yaffs_Spare *spare);
|
||||
int nandmtd_EraseBlockInNAND(yaffs_Device *dev, int blockNumber);
|
||||
int nandmtd_InitialiseNAND(yaffs_Device *dev);
|
||||
#endif
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#include "yportenv.h"
|
||||
#include "yaffs_guts.h"
|
||||
#include "yaffs_packedtags1.h"
|
||||
#include "yaffs_tagscompat.h" // for yaffs_CalcTagsECC
|
||||
#include "yaffs_tagscompat.h" /* for yaffs_CalcTagsECC */
|
||||
|
||||
#include "linux/kernel.h"
|
||||
#include "linux/version.h"
|
||||
|
@ -34,9 +34,9 @@
|
|||
#include "linux/mtd/mtd.h"
|
||||
|
||||
/* Don't compile this module if we don't have MTD's mtd_oob_ops interface */
|
||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
|
||||
#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17))
|
||||
|
||||
const char *yaffs_mtdif1_c_version = "$Id: yaffs_mtdif1.c,v 1.3 2007/05/15 20:16:11 ian Exp $";
|
||||
const char *yaffs_mtdif1_c_version = "$Id: yaffs_mtdif1.c,v 1.10 2009-03-09 07:41:10 charles Exp $";
|
||||
|
||||
#ifndef CONFIG_YAFFS_9BYTE_TAGS
|
||||
# define YTAG1_SIZE 8
|
||||
|
@ -89,9 +89,9 @@ static struct nand_ecclayout nand_oob_16 = {
|
|||
* Returns YAFFS_OK or YAFFS_FAIL.
|
||||
*/
|
||||
int nandmtd1_WriteChunkWithTagsToNAND(yaffs_Device *dev,
|
||||
int chunkInNAND, const __u8 * data, const yaffs_ExtendedTags * etags)
|
||||
int chunkInNAND, const __u8 *data, const yaffs_ExtendedTags *etags)
|
||||
{
|
||||
struct mtd_info * mtd = dev->genericDevice;
|
||||
struct mtd_info *mtd = dev->genericDevice;
|
||||
int chunkBytes = dev->nDataBytesPerChunk;
|
||||
loff_t addr = ((loff_t)chunkInNAND) * chunkBytes;
|
||||
struct mtd_oob_ops ops;
|
||||
|
@ -146,7 +146,7 @@ int nandmtd1_WriteChunkWithTagsToNAND(yaffs_Device *dev,
|
|||
|
||||
/* Return with empty ExtendedTags but add eccResult.
|
||||
*/
|
||||
static int rettags(yaffs_ExtendedTags * etags, int eccResult, int retval)
|
||||
static int rettags(yaffs_ExtendedTags *etags, int eccResult, int retval)
|
||||
{
|
||||
if (etags) {
|
||||
memset(etags, 0, sizeof(*etags));
|
||||
|
@ -169,9 +169,9 @@ static int rettags(yaffs_ExtendedTags * etags, int eccResult, int retval)
|
|||
* Returns YAFFS_OK or YAFFS_FAIL.
|
||||
*/
|
||||
int nandmtd1_ReadChunkWithTagsFromNAND(yaffs_Device *dev,
|
||||
int chunkInNAND, __u8 * data, yaffs_ExtendedTags * etags)
|
||||
int chunkInNAND, __u8 *data, yaffs_ExtendedTags *etags)
|
||||
{
|
||||
struct mtd_info * mtd = dev->genericDevice;
|
||||
struct mtd_info *mtd = dev->genericDevice;
|
||||
int chunkBytes = dev->nDataBytesPerChunk;
|
||||
loff_t addr = ((loff_t)chunkInNAND) * chunkBytes;
|
||||
int eccres = YAFFS_ECC_RESULT_NO_ERROR;
|
||||
|
@ -189,7 +189,7 @@ int nandmtd1_ReadChunkWithTagsFromNAND(yaffs_Device *dev,
|
|||
ops.datbuf = data;
|
||||
ops.oobbuf = (__u8 *)&pt1;
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
|
||||
#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.
|
||||
*/
|
||||
|
@ -284,11 +284,11 @@ int nandmtd1_ReadChunkWithTagsFromNAND(yaffs_Device *dev,
|
|||
*/
|
||||
int nandmtd1_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo)
|
||||
{
|
||||
struct mtd_info * mtd = dev->genericDevice;
|
||||
struct mtd_info *mtd = dev->genericDevice;
|
||||
int blocksize = dev->nChunksPerBlock * dev->nDataBytesPerChunk;
|
||||
int retval;
|
||||
|
||||
yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, "marking block %d bad", blockNo);
|
||||
yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, "marking block %d bad\n", blockNo);
|
||||
|
||||
retval = mtd->block_markbad(mtd, (loff_t)blocksize * blockNo);
|
||||
return (retval) ? YAFFS_FAIL : YAFFS_OK;
|
||||
|
@ -298,7 +298,7 @@ int nandmtd1_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo)
|
|||
*
|
||||
* Returns YAFFS_OK or YAFFS_FAIL.
|
||||
*/
|
||||
static int nandmtd1_TestPrerequists(struct mtd_info * mtd)
|
||||
static int nandmtd1_TestPrerequists(struct mtd_info *mtd)
|
||||
{
|
||||
/* 2.6.18 has mtd->ecclayout->oobavail */
|
||||
/* 2.6.21 has mtd->ecclayout->oobavail and mtd->oobavail */
|
||||
|
@ -323,10 +323,11 @@ static int nandmtd1_TestPrerequists(struct mtd_info * mtd)
|
|||
* Always returns YAFFS_OK.
|
||||
*/
|
||||
int nandmtd1_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
|
||||
yaffs_BlockState * pState, int *pSequenceNumber)
|
||||
yaffs_BlockState *pState, __u32 *pSequenceNumber)
|
||||
{
|
||||
struct mtd_info * mtd = dev->genericDevice;
|
||||
struct mtd_info *mtd = dev->genericDevice;
|
||||
int chunkNo = blockNo * dev->nChunksPerBlock;
|
||||
loff_t addr = (loff_t)chunkNo * dev->nDataBytesPerChunk;
|
||||
yaffs_ExtendedTags etags;
|
||||
int state = YAFFS_BLOCK_STATE_DEAD;
|
||||
int seqnum = 0;
|
||||
|
@ -335,21 +336,22 @@ int nandmtd1_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
|
|||
/* 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_TestPrerequists(mtd) != YAFFS_OK) {
|
||||
if (nandmtd1_TestPrerequists(mtd) != YAFFS_OK)
|
||||
return YAFFS_FAIL;
|
||||
}
|
||||
|
||||
retval = nandmtd1_ReadChunkWithTagsFromNAND(dev, chunkNo, NULL, &etags);
|
||||
etags.blockBad = (mtd->block_isbad)(mtd, addr);
|
||||
if (etags.blockBad) {
|
||||
yaffs_trace(YAFFS_TRACE_BAD_BLOCKS,
|
||||
"block %d is marked bad", blockNo);
|
||||
"block %d is marked bad\n", blockNo);
|
||||
state = YAFFS_BLOCK_STATE_DEAD;
|
||||
}
|
||||
else if (etags.chunkUsed) {
|
||||
} else if (etags.eccResult != YAFFS_ECC_RESULT_NO_ERROR) {
|
||||
/* bad tags, need to look more closely */
|
||||
state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
|
||||
} else if (etags.chunkUsed) {
|
||||
state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
|
||||
seqnum = etags.sequenceNumber;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
state = YAFFS_BLOCK_STATE_EMPTY;
|
||||
}
|
||||
|
||||
|
@ -360,4 +362,4 @@ int nandmtd1_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
|
|||
return YAFFS_OK;
|
||||
}
|
||||
|
||||
#endif /*KERNEL_VERSION*/
|
||||
#endif /*MTD_VERSION*/
|
||||
|
|
|
@ -14,15 +14,15 @@
|
|||
#ifndef __YAFFS_MTDIF1_H__
|
||||
#define __YAFFS_MTDIF1_H__
|
||||
|
||||
int nandmtd1_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND,
|
||||
const __u8 * data, const yaffs_ExtendedTags * tags);
|
||||
int nandmtd1_WriteChunkWithTagsToNAND(yaffs_Device *dev, int chunkInNAND,
|
||||
const __u8 *data, const yaffs_ExtendedTags *tags);
|
||||
|
||||
int nandmtd1_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,
|
||||
__u8 * data, yaffs_ExtendedTags * tags);
|
||||
int nandmtd1_ReadChunkWithTagsFromNAND(yaffs_Device *dev, int chunkInNAND,
|
||||
__u8 *data, yaffs_ExtendedTags *tags);
|
||||
|
||||
int nandmtd1_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo);
|
||||
|
||||
int nandmtd1_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
|
||||
yaffs_BlockState * state, int *sequenceNumber);
|
||||
yaffs_BlockState *state, __u32 *sequenceNumber);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
/* mtd interface for YAFFS2 */
|
||||
|
||||
const char *yaffs_mtdif2_c_version =
|
||||
"$Id: yaffs_mtdif2.c,v 1.17 2007-02-14 01:09:06 wookey Exp $";
|
||||
"$Id: yaffs_mtdif2.c,v 1.23 2009-03-06 17:20:53 wookey Exp $";
|
||||
|
||||
#include "yportenv.h"
|
||||
|
||||
|
@ -27,19 +27,23 @@ const char *yaffs_mtdif2_c_version =
|
|||
|
||||
#include "yaffs_packedtags2.h"
|
||||
|
||||
int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND,
|
||||
const __u8 * data,
|
||||
const yaffs_ExtendedTags * tags)
|
||||
/* NB For use with inband tags....
|
||||
* We assume that the data buffer is of size totalBytersPerChunk so that we can also
|
||||
* use it to load the tags.
|
||||
*/
|
||||
int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device *dev, int chunkInNAND,
|
||||
const __u8 *data,
|
||||
const yaffs_ExtendedTags *tags)
|
||||
{
|
||||
struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
|
||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
|
||||
#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 = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
|
||||
loff_t addr;
|
||||
|
||||
yaffs_PackedTags2 pt;
|
||||
|
||||
|
@ -48,46 +52,40 @@ int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND,
|
|||
("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p"
|
||||
TENDSTR), chunkInNAND, data, tags));
|
||||
|
||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
|
||||
if (tags)
|
||||
yaffs_PackTags2(&pt, tags);
|
||||
else
|
||||
BUG(); /* both tags and data should always be present */
|
||||
|
||||
if (data) {
|
||||
ops.mode = MTD_OOB_AUTO;
|
||||
ops.ooblen = sizeof(pt);
|
||||
ops.len = dev->nDataBytesPerChunk;
|
||||
ops.ooboffs = 0;
|
||||
ops.datbuf = (__u8 *)data;
|
||||
ops.oobbuf = (void *)&pt;
|
||||
retval = mtd->write_oob(mtd, addr, &ops);
|
||||
addr = ((loff_t) chunkInNAND) * dev->totalBytesPerChunk;
|
||||
|
||||
/* 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->inbandTags) {
|
||||
yaffs_PackedTags2TagsPart *pt2tp;
|
||||
pt2tp = (yaffs_PackedTags2TagsPart *)(data + dev->nDataBytesPerChunk);
|
||||
yaffs_PackTags2TagsPart(pt2tp, tags);
|
||||
} else
|
||||
BUG(); /* both tags and data should always be present */
|
||||
#else
|
||||
if (tags) {
|
||||
yaffs_PackTags2(&pt, tags);
|
||||
}
|
||||
|
||||
if (data && tags) {
|
||||
if (dev->useNANDECC)
|
||||
retval =
|
||||
mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,
|
||||
&dummy, data, (__u8 *) & pt, NULL);
|
||||
else
|
||||
retval =
|
||||
mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,
|
||||
&dummy, data, (__u8 *) & pt, NULL);
|
||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
|
||||
ops.mode = MTD_OOB_AUTO;
|
||||
ops.ooblen = (dev->inbandTags) ? 0 : sizeof(pt);
|
||||
ops.len = dev->totalBytesPerChunk;
|
||||
ops.ooboffs = 0;
|
||||
ops.datbuf = (__u8 *)data;
|
||||
ops.oobbuf = (dev->inbandTags) ? NULL : (void *)&pt;
|
||||
retval = mtd->write_oob(mtd, addr, &ops);
|
||||
|
||||
#else
|
||||
if (!dev->inbandTags) {
|
||||
retval =
|
||||
mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,
|
||||
&dummy, data, (__u8 *) &pt, NULL);
|
||||
} else {
|
||||
if (data)
|
||||
retval =
|
||||
mtd->write(mtd, addr, dev->nDataBytesPerChunk, &dummy,
|
||||
data);
|
||||
if (tags)
|
||||
retval =
|
||||
mtd->write_oob(mtd, addr, mtd->oobsize, &dummy,
|
||||
(__u8 *) & pt);
|
||||
|
||||
retval =
|
||||
mtd->write(mtd, addr, dev->totalBytesPerChunk, &dummy,
|
||||
data);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -97,17 +95,18 @@ int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND,
|
|||
return YAFFS_FAIL;
|
||||
}
|
||||
|
||||
int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,
|
||||
__u8 * data, yaffs_ExtendedTags * tags)
|
||||
int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device *dev, int chunkInNAND,
|
||||
__u8 *data, yaffs_ExtendedTags *tags)
|
||||
{
|
||||
struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
|
||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
|
||||
#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17))
|
||||
struct mtd_oob_ops ops;
|
||||
#endif
|
||||
size_t dummy;
|
||||
int retval = 0;
|
||||
int localData = 0;
|
||||
|
||||
loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
|
||||
loff_t addr = ((loff_t) chunkInNAND) * dev->totalBytesPerChunk;
|
||||
|
||||
yaffs_PackedTags2 pt;
|
||||
|
||||
|
@ -116,9 +115,20 @@ int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,
|
|||
("nandmtd2_ReadChunkWithTagsFromNAND chunk %d data %p tags %p"
|
||||
TENDSTR), chunkInNAND, data, tags));
|
||||
|
||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
|
||||
if (data && !tags)
|
||||
retval = mtd->read(mtd, addr, dev->nDataBytesPerChunk,
|
||||
if (dev->inbandTags) {
|
||||
|
||||
if (!data) {
|
||||
localData = 1;
|
||||
data = yaffs_GetTempBuffer(dev, __LINE__);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
|
||||
if (dev->inbandTags || (data && !tags))
|
||||
retval = mtd->read(mtd, addr, dev->totalBytesPerChunk,
|
||||
&dummy, data);
|
||||
else if (tags) {
|
||||
ops.mode = MTD_OOB_AUTO;
|
||||
|
@ -130,38 +140,42 @@ int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,
|
|||
retval = mtd->read_oob(mtd, addr, &ops);
|
||||
}
|
||||
#else
|
||||
if (data && tags) {
|
||||
if (dev->useNANDECC) {
|
||||
retval =
|
||||
mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk,
|
||||
if (!dev->inbandTags && data && tags) {
|
||||
|
||||
retval = mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk,
|
||||
&dummy, data, dev->spareBuffer,
|
||||
NULL);
|
||||
} else {
|
||||
retval =
|
||||
mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk,
|
||||
&dummy, data, dev->spareBuffer,
|
||||
NULL);
|
||||
}
|
||||
} else {
|
||||
if (data)
|
||||
retval =
|
||||
mtd->read(mtd, addr, dev->nDataBytesPerChunk, &dummy,
|
||||
data);
|
||||
if (tags)
|
||||
if (!dev->inbandTags && tags)
|
||||
retval =
|
||||
mtd->read_oob(mtd, addr, mtd->oobsize, &dummy,
|
||||
dev->spareBuffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
memcpy(&pt, dev->spareBuffer, sizeof(pt));
|
||||
|
||||
if (tags)
|
||||
yaffs_UnpackTags2(tags, &pt);
|
||||
if (dev->inbandTags) {
|
||||
if (tags) {
|
||||
yaffs_PackedTags2TagsPart *pt2tp;
|
||||
pt2tp = (yaffs_PackedTags2TagsPart *)&data[dev->nDataBytesPerChunk];
|
||||
yaffs_UnpackTags2TagsPart(tags, pt2tp);
|
||||
}
|
||||
} else {
|
||||
if (tags) {
|
||||
memcpy(&pt, dev->spareBuffer, sizeof(pt));
|
||||
yaffs_UnpackTags2(tags, &pt);
|
||||
}
|
||||
}
|
||||
|
||||
if(tags && retval == -EBADMSG && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR)
|
||||
if (localData)
|
||||
yaffs_ReleaseTempBuffer(dev, data, __LINE__);
|
||||
|
||||
if (tags && retval == -EBADMSG && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR)
|
||||
tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;
|
||||
|
||||
if (retval == 0)
|
||||
return YAFFS_OK;
|
||||
else
|
||||
|
@ -178,7 +192,7 @@ int nandmtd2_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo)
|
|||
retval =
|
||||
mtd->block_markbad(mtd,
|
||||
blockNo * dev->nChunksPerBlock *
|
||||
dev->nDataBytesPerChunk);
|
||||
dev->totalBytesPerChunk);
|
||||
|
||||
if (retval == 0)
|
||||
return YAFFS_OK;
|
||||
|
@ -188,7 +202,7 @@ int nandmtd2_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo)
|
|||
}
|
||||
|
||||
int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
|
||||
yaffs_BlockState * state, int *sequenceNumber)
|
||||
yaffs_BlockState *state, __u32 *sequenceNumber)
|
||||
{
|
||||
struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
|
||||
int retval;
|
||||
|
@ -198,7 +212,7 @@ int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
|
|||
retval =
|
||||
mtd->block_isbad(mtd,
|
||||
blockNo * dev->nChunksPerBlock *
|
||||
dev->nDataBytesPerChunk);
|
||||
dev->totalBytesPerChunk);
|
||||
|
||||
if (retval) {
|
||||
T(YAFFS_TRACE_MTD, (TSTR("block is bad" TENDSTR)));
|
||||
|
|
|
@ -17,13 +17,13 @@
|
|||
#define __YAFFS_MTDIF2_H__
|
||||
|
||||
#include "yaffs_guts.h"
|
||||
int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND,
|
||||
const __u8 * data,
|
||||
const yaffs_ExtendedTags * tags);
|
||||
int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,
|
||||
__u8 * data, yaffs_ExtendedTags * tags);
|
||||
int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device *dev, int chunkInNAND,
|
||||
const __u8 *data,
|
||||
const yaffs_ExtendedTags *tags);
|
||||
int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device *dev, int chunkInNAND,
|
||||
__u8 *data, yaffs_ExtendedTags *tags);
|
||||
int nandmtd2_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo);
|
||||
int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
|
||||
yaffs_BlockState * state, int *sequenceNumber);
|
||||
yaffs_BlockState *state, __u32 *sequenceNumber);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -12,16 +12,17 @@
|
|||
*/
|
||||
|
||||
const char *yaffs_nand_c_version =
|
||||
"$Id: yaffs_nand.c,v 1.7 2007-02-14 01:09:06 wookey Exp $";
|
||||
"$Id: yaffs_nand.c,v 1.10 2009-03-06 17:20:54 wookey Exp $";
|
||||
|
||||
#include "yaffs_nand.h"
|
||||
#include "yaffs_tagscompat.h"
|
||||
#include "yaffs_tagsvalidity.h"
|
||||
|
||||
#include "yaffs_getblockinfo.h"
|
||||
|
||||
int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,
|
||||
__u8 * buffer,
|
||||
yaffs_ExtendedTags * tags)
|
||||
int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device *dev, int chunkInNAND,
|
||||
__u8 *buffer,
|
||||
yaffs_ExtendedTags *tags)
|
||||
{
|
||||
int result;
|
||||
yaffs_ExtendedTags localTags;
|
||||
|
@ -29,7 +30,7 @@ int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,
|
|||
int realignedChunkInNAND = chunkInNAND - dev->chunkOffset;
|
||||
|
||||
/* If there are no tags provided, use local tags to get prioritised gc working */
|
||||
if(!tags)
|
||||
if (!tags)
|
||||
tags = &localTags;
|
||||
|
||||
if (dev->readChunkWithTagsFromNAND)
|
||||
|
@ -40,20 +41,20 @@ int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,
|
|||
realignedChunkInNAND,
|
||||
buffer,
|
||||
tags);
|
||||
if(tags &&
|
||||
tags->eccResult > YAFFS_ECC_RESULT_NO_ERROR){
|
||||
if (tags &&
|
||||
tags->eccResult > YAFFS_ECC_RESULT_NO_ERROR) {
|
||||
|
||||
yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, chunkInNAND/dev->nChunksPerBlock);
|
||||
yaffs_HandleChunkError(dev,bi);
|
||||
yaffs_HandleChunkError(dev, bi);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int yaffs_WriteChunkWithTagsToNAND(yaffs_Device * dev,
|
||||
int yaffs_WriteChunkWithTagsToNAND(yaffs_Device *dev,
|
||||
int chunkInNAND,
|
||||
const __u8 * buffer,
|
||||
yaffs_ExtendedTags * tags)
|
||||
const __u8 *buffer,
|
||||
yaffs_ExtendedTags *tags)
|
||||
{
|
||||
chunkInNAND -= dev->chunkOffset;
|
||||
|
||||
|
@ -84,7 +85,7 @@ int yaffs_WriteChunkWithTagsToNAND(yaffs_Device * dev,
|
|||
tags);
|
||||
}
|
||||
|
||||
int yaffs_MarkBlockBad(yaffs_Device * dev, int blockNo)
|
||||
int yaffs_MarkBlockBad(yaffs_Device *dev, int blockNo)
|
||||
{
|
||||
blockNo -= dev->blockOffset;
|
||||
|
||||
|
@ -95,10 +96,10 @@ int yaffs_MarkBlockBad(yaffs_Device * dev, int blockNo)
|
|||
return yaffs_TagsCompatabilityMarkNANDBlockBad(dev, blockNo);
|
||||
}
|
||||
|
||||
int yaffs_QueryInitialBlockState(yaffs_Device * dev,
|
||||
int yaffs_QueryInitialBlockState(yaffs_Device *dev,
|
||||
int blockNo,
|
||||
yaffs_BlockState * state,
|
||||
unsigned *sequenceNumber)
|
||||
yaffs_BlockState *state,
|
||||
__u32 *sequenceNumber)
|
||||
{
|
||||
blockNo -= dev->blockOffset;
|
||||
|
||||
|
|
|
@ -19,21 +19,21 @@
|
|||
|
||||
|
||||
|
||||
int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,
|
||||
__u8 * buffer,
|
||||
yaffs_ExtendedTags * tags);
|
||||
int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device *dev, int chunkInNAND,
|
||||
__u8 *buffer,
|
||||
yaffs_ExtendedTags *tags);
|
||||
|
||||
int yaffs_WriteChunkWithTagsToNAND(yaffs_Device * dev,
|
||||
int chunkInNAND,
|
||||
const __u8 * buffer,
|
||||
yaffs_ExtendedTags * tags);
|
||||
int yaffs_WriteChunkWithTagsToNAND(yaffs_Device *dev,
|
||||
int chunkInNAND,
|
||||
const __u8 *buffer,
|
||||
yaffs_ExtendedTags *tags);
|
||||
|
||||
int yaffs_MarkBlockBad(yaffs_Device * dev, int blockNo);
|
||||
int yaffs_MarkBlockBad(yaffs_Device *dev, int blockNo);
|
||||
|
||||
int yaffs_QueryInitialBlockState(yaffs_Device * dev,
|
||||
int blockNo,
|
||||
yaffs_BlockState * state,
|
||||
unsigned *sequenceNumber);
|
||||
int yaffs_QueryInitialBlockState(yaffs_Device *dev,
|
||||
int blockNo,
|
||||
yaffs_BlockState *state,
|
||||
unsigned *sequenceNumber);
|
||||
|
||||
int yaffs_EraseBlockInNAND(struct yaffs_DeviceStruct *dev,
|
||||
int blockInNAND);
|
||||
|
|
|
@ -21,14 +21,14 @@
|
|||
#include "yaffs_guts.h"
|
||||
|
||||
int nandemul2k_WriteChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev,
|
||||
int chunkInNAND, const __u8 * data,
|
||||
yaffs_ExtendedTags * tags);
|
||||
int chunkInNAND, const __u8 *data,
|
||||
const yaffs_ExtendedTags *tags);
|
||||
int nandemul2k_ReadChunkWithTagsFromNAND(struct yaffs_DeviceStruct *dev,
|
||||
int chunkInNAND, __u8 * data,
|
||||
yaffs_ExtendedTags * tags);
|
||||
int chunkInNAND, __u8 *data,
|
||||
yaffs_ExtendedTags *tags);
|
||||
int nandemul2k_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo);
|
||||
int nandemul2k_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
|
||||
yaffs_BlockState * state, int *sequenceNumber);
|
||||
yaffs_BlockState *state, __u32 *sequenceNumber);
|
||||
int nandemul2k_EraseBlockInNAND(struct yaffs_DeviceStruct *dev,
|
||||
int blockInNAND);
|
||||
int nandemul2k_InitialiseNAND(struct yaffs_DeviceStruct *dev);
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
#include "yaffs_packedtags1.h"
|
||||
#include "yportenv.h"
|
||||
|
||||
void yaffs_PackTags1(yaffs_PackedTags1 * pt, const yaffs_ExtendedTags * t)
|
||||
void yaffs_PackTags1(yaffs_PackedTags1 *pt, const yaffs_ExtendedTags *t)
|
||||
{
|
||||
pt->chunkId = t->chunkId;
|
||||
pt->serialNumber = t->serialNumber;
|
||||
|
@ -27,7 +27,7 @@ void yaffs_PackTags1(yaffs_PackedTags1 * pt, const yaffs_ExtendedTags * t)
|
|||
|
||||
}
|
||||
|
||||
void yaffs_UnpackTags1(yaffs_ExtendedTags * t, const yaffs_PackedTags1 * pt)
|
||||
void yaffs_UnpackTags1(yaffs_ExtendedTags *t, const yaffs_PackedTags1 *pt)
|
||||
{
|
||||
static const __u8 allFF[] =
|
||||
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
|
@ -35,9 +35,8 @@ void yaffs_UnpackTags1(yaffs_ExtendedTags * t, const yaffs_PackedTags1 * pt)
|
|||
|
||||
if (memcmp(allFF, pt, sizeof(yaffs_PackedTags1))) {
|
||||
t->blockBad = 0;
|
||||
if (pt->shouldBeFF != 0xFFFFFFFF) {
|
||||
if (pt->shouldBeFF != 0xFFFFFFFF)
|
||||
t->blockBad = 1;
|
||||
}
|
||||
t->chunkUsed = 1;
|
||||
t->objectId = pt->objectId;
|
||||
t->chunkId = pt->chunkId;
|
||||
|
@ -47,6 +46,5 @@ void yaffs_UnpackTags1(yaffs_ExtendedTags * t, const yaffs_PackedTags1 * pt)
|
|||
t->serialNumber = pt->serialNumber;
|
||||
} else {
|
||||
memset(t, 0, sizeof(yaffs_ExtendedTags));
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,6 +32,6 @@ typedef struct {
|
|||
|
||||
} yaffs_PackedTags1;
|
||||
|
||||
void yaffs_PackTags1(yaffs_PackedTags1 * pt, const yaffs_ExtendedTags * t);
|
||||
void yaffs_UnpackTags1(yaffs_ExtendedTags * t, const yaffs_PackedTags1 * pt);
|
||||
void yaffs_PackTags1(yaffs_PackedTags1 *pt, const yaffs_ExtendedTags *t);
|
||||
void yaffs_UnpackTags1(yaffs_ExtendedTags *t, const yaffs_PackedTags1 *pt);
|
||||
#endif
|
||||
|
|
|
@ -37,60 +37,68 @@
|
|||
#define EXTRA_OBJECT_TYPE_SHIFT (28)
|
||||
#define EXTRA_OBJECT_TYPE_MASK ((0x0F) << EXTRA_OBJECT_TYPE_SHIFT)
|
||||
|
||||
static void yaffs_DumpPackedTags2(const yaffs_PackedTags2 * pt)
|
||||
|
||||
static void yaffs_DumpPackedTags2TagsPart(const yaffs_PackedTags2TagsPart *ptt)
|
||||
{
|
||||
T(YAFFS_TRACE_MTD,
|
||||
(TSTR("packed tags obj %d chunk %d byte %d seq %d" TENDSTR),
|
||||
pt->t.objectId, pt->t.chunkId, pt->t.byteCount,
|
||||
pt->t.sequenceNumber));
|
||||
ptt->objectId, ptt->chunkId, ptt->byteCount,
|
||||
ptt->sequenceNumber));
|
||||
}
|
||||
static void yaffs_DumpPackedTags2(const yaffs_PackedTags2 *pt)
|
||||
{
|
||||
yaffs_DumpPackedTags2TagsPart(&pt->t);
|
||||
}
|
||||
|
||||
static void yaffs_DumpTags2(const yaffs_ExtendedTags * t)
|
||||
static void yaffs_DumpTags2(const yaffs_ExtendedTags *t)
|
||||
{
|
||||
T(YAFFS_TRACE_MTD,
|
||||
(TSTR
|
||||
("ext.tags eccres %d blkbad %d chused %d obj %d chunk%d byte "
|
||||
"%d del %d ser %d seq %d"
|
||||
("ext.tags eccres %d blkbad %d chused %d obj %d chunk%d byte %d del %d ser %d seq %d"
|
||||
TENDSTR), t->eccResult, t->blockBad, t->chunkUsed, t->objectId,
|
||||
t->chunkId, t->byteCount, t->chunkDeleted, t->serialNumber,
|
||||
t->sequenceNumber));
|
||||
|
||||
}
|
||||
|
||||
void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags * t)
|
||||
void yaffs_PackTags2TagsPart(yaffs_PackedTags2TagsPart *ptt,
|
||||
const yaffs_ExtendedTags *t)
|
||||
{
|
||||
pt->t.chunkId = t->chunkId;
|
||||
pt->t.sequenceNumber = t->sequenceNumber;
|
||||
pt->t.byteCount = t->byteCount;
|
||||
pt->t.objectId = t->objectId;
|
||||
ptt->chunkId = t->chunkId;
|
||||
ptt->sequenceNumber = t->sequenceNumber;
|
||||
ptt->byteCount = t->byteCount;
|
||||
ptt->objectId = t->objectId;
|
||||
|
||||
if (t->chunkId == 0 && t->extraHeaderInfoAvailable) {
|
||||
/* Store the extra header info instead */
|
||||
/* We save the parent object in the chunkId */
|
||||
pt->t.chunkId = EXTRA_HEADER_INFO_FLAG
|
||||
ptt->chunkId = EXTRA_HEADER_INFO_FLAG
|
||||
| t->extraParentObjectId;
|
||||
if (t->extraIsShrinkHeader) {
|
||||
pt->t.chunkId |= EXTRA_SHRINK_FLAG;
|
||||
}
|
||||
if (t->extraShadows) {
|
||||
pt->t.chunkId |= EXTRA_SHADOWS_FLAG;
|
||||
}
|
||||
if (t->extraIsShrinkHeader)
|
||||
ptt->chunkId |= EXTRA_SHRINK_FLAG;
|
||||
if (t->extraShadows)
|
||||
ptt->chunkId |= EXTRA_SHADOWS_FLAG;
|
||||
|
||||
pt->t.objectId &= ~EXTRA_OBJECT_TYPE_MASK;
|
||||
pt->t.objectId |=
|
||||
ptt->objectId &= ~EXTRA_OBJECT_TYPE_MASK;
|
||||
ptt->objectId |=
|
||||
(t->extraObjectType << EXTRA_OBJECT_TYPE_SHIFT);
|
||||
|
||||
if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) {
|
||||
pt->t.byteCount = t->extraEquivalentObjectId;
|
||||
} else if (t->extraObjectType == YAFFS_OBJECT_TYPE_FILE) {
|
||||
pt->t.byteCount = t->extraFileLength;
|
||||
} else {
|
||||
pt->t.byteCount = 0;
|
||||
}
|
||||
if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK)
|
||||
ptt->byteCount = t->extraEquivalentObjectId;
|
||||
else if (t->extraObjectType == YAFFS_OBJECT_TYPE_FILE)
|
||||
ptt->byteCount = t->extraFileLength;
|
||||
else
|
||||
ptt->byteCount = 0;
|
||||
}
|
||||
|
||||
yaffs_DumpPackedTags2(pt);
|
||||
yaffs_DumpPackedTags2TagsPart(ptt);
|
||||
yaffs_DumpTags2(t);
|
||||
}
|
||||
|
||||
|
||||
void yaffs_PackTags2(yaffs_PackedTags2 *pt, const yaffs_ExtendedTags *t)
|
||||
{
|
||||
yaffs_PackTags2TagsPart(&pt->t, t);
|
||||
|
||||
#ifndef YAFFS_IGNORE_TAGS_ECC
|
||||
{
|
||||
|
@ -101,20 +109,63 @@ void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags * t)
|
|||
#endif
|
||||
}
|
||||
|
||||
void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 * pt)
|
||||
|
||||
void yaffs_UnpackTags2TagsPart(yaffs_ExtendedTags *t,
|
||||
yaffs_PackedTags2TagsPart *ptt)
|
||||
{
|
||||
|
||||
memset(t, 0, sizeof(yaffs_ExtendedTags));
|
||||
|
||||
yaffs_InitialiseTags(t);
|
||||
|
||||
if (ptt->sequenceNumber != 0xFFFFFFFF) {
|
||||
t->blockBad = 0;
|
||||
t->chunkUsed = 1;
|
||||
t->objectId = ptt->objectId;
|
||||
t->chunkId = ptt->chunkId;
|
||||
t->byteCount = ptt->byteCount;
|
||||
t->chunkDeleted = 0;
|
||||
t->serialNumber = 0;
|
||||
t->sequenceNumber = ptt->sequenceNumber;
|
||||
|
||||
/* Do extra header info stuff */
|
||||
|
||||
if (ptt->chunkId & EXTRA_HEADER_INFO_FLAG) {
|
||||
t->chunkId = 0;
|
||||
t->byteCount = 0;
|
||||
|
||||
t->extraHeaderInfoAvailable = 1;
|
||||
t->extraParentObjectId =
|
||||
ptt->chunkId & (~(ALL_EXTRA_FLAGS));
|
||||
t->extraIsShrinkHeader =
|
||||
(ptt->chunkId & EXTRA_SHRINK_FLAG) ? 1 : 0;
|
||||
t->extraShadows =
|
||||
(ptt->chunkId & EXTRA_SHADOWS_FLAG) ? 1 : 0;
|
||||
t->extraObjectType =
|
||||
ptt->objectId >> EXTRA_OBJECT_TYPE_SHIFT;
|
||||
t->objectId &= ~EXTRA_OBJECT_TYPE_MASK;
|
||||
|
||||
if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK)
|
||||
t->extraEquivalentObjectId = ptt->byteCount;
|
||||
else
|
||||
t->extraFileLength = ptt->byteCount;
|
||||
}
|
||||
}
|
||||
|
||||
yaffs_DumpPackedTags2TagsPart(ptt);
|
||||
yaffs_DumpTags2(t);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void yaffs_UnpackTags2(yaffs_ExtendedTags *t, yaffs_PackedTags2 *pt)
|
||||
{
|
||||
|
||||
yaffs_ECCResult eccResult = YAFFS_ECC_RESULT_NO_ERROR;
|
||||
|
||||
if (pt->t.sequenceNumber != 0xFFFFFFFF) {
|
||||
/* Page is in use */
|
||||
#ifdef YAFFS_IGNORE_TAGS_ECC
|
||||
{
|
||||
t->eccResult = YAFFS_ECC_RESULT_NO_ERROR;
|
||||
}
|
||||
#else
|
||||
#ifndef YAFFS_IGNORE_TAGS_ECC
|
||||
{
|
||||
yaffs_ECCOther ecc;
|
||||
int result;
|
||||
|
@ -127,56 +178,29 @@ void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 * pt)
|
|||
sizeof
|
||||
(yaffs_PackedTags2TagsPart),
|
||||
&pt->ecc, &ecc);
|
||||
switch(result){
|
||||
case 0:
|
||||
t->eccResult = YAFFS_ECC_RESULT_NO_ERROR;
|
||||
break;
|
||||
case 1:
|
||||
t->eccResult = YAFFS_ECC_RESULT_FIXED;
|
||||
break;
|
||||
case -1:
|
||||
t->eccResult = YAFFS_ECC_RESULT_UNFIXED;
|
||||
break;
|
||||
default:
|
||||
t->eccResult = YAFFS_ECC_RESULT_UNKNOWN;
|
||||
switch (result) {
|
||||
case 0:
|
||||
eccResult = YAFFS_ECC_RESULT_NO_ERROR;
|
||||
break;
|
||||
case 1:
|
||||
eccResult = YAFFS_ECC_RESULT_FIXED;
|
||||
break;
|
||||
case -1:
|
||||
eccResult = YAFFS_ECC_RESULT_UNFIXED;
|
||||
break;
|
||||
default:
|
||||
eccResult = YAFFS_ECC_RESULT_UNKNOWN;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
t->blockBad = 0;
|
||||
t->chunkUsed = 1;
|
||||
t->objectId = pt->t.objectId;
|
||||
t->chunkId = pt->t.chunkId;
|
||||
t->byteCount = pt->t.byteCount;
|
||||
t->chunkDeleted = 0;
|
||||
t->serialNumber = 0;
|
||||
t->sequenceNumber = pt->t.sequenceNumber;
|
||||
|
||||
/* Do extra header info stuff */
|
||||
|
||||
if (pt->t.chunkId & EXTRA_HEADER_INFO_FLAG) {
|
||||
t->chunkId = 0;
|
||||
t->byteCount = 0;
|
||||
|
||||
t->extraHeaderInfoAvailable = 1;
|
||||
t->extraParentObjectId =
|
||||
pt->t.chunkId & (~(ALL_EXTRA_FLAGS));
|
||||
t->extraIsShrinkHeader =
|
||||
(pt->t.chunkId & EXTRA_SHRINK_FLAG) ? 1 : 0;
|
||||
t->extraShadows =
|
||||
(pt->t.chunkId & EXTRA_SHADOWS_FLAG) ? 1 : 0;
|
||||
t->extraObjectType =
|
||||
pt->t.objectId >> EXTRA_OBJECT_TYPE_SHIFT;
|
||||
t->objectId &= ~EXTRA_OBJECT_TYPE_MASK;
|
||||
|
||||
if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) {
|
||||
t->extraEquivalentObjectId = pt->t.byteCount;
|
||||
} else {
|
||||
t->extraFileLength = pt->t.byteCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
yaffs_UnpackTags2TagsPart(t, &pt->t);
|
||||
|
||||
t->eccResult = eccResult;
|
||||
|
||||
yaffs_DumpPackedTags2(pt);
|
||||
yaffs_DumpTags2(t);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,11 @@ typedef struct {
|
|||
yaffs_ECCOther ecc;
|
||||
} yaffs_PackedTags2;
|
||||
|
||||
void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags * t);
|
||||
void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 * pt);
|
||||
/* Full packed tags with ECC, used for oob tags */
|
||||
void yaffs_PackTags2(yaffs_PackedTags2 *pt, const yaffs_ExtendedTags *t);
|
||||
void yaffs_UnpackTags2(yaffs_ExtendedTags *t, yaffs_PackedTags2 *pt);
|
||||
|
||||
/* Only the tags part (no ECC for use with inband tags */
|
||||
void yaffs_PackTags2TagsPart(yaffs_PackedTags2TagsPart *pt, const yaffs_ExtendedTags *t);
|
||||
void yaffs_UnpackTags2TagsPart(yaffs_ExtendedTags *t, yaffs_PackedTags2TagsPart *pt);
|
||||
#endif
|
||||
|
|
|
@ -28,12 +28,12 @@
|
|||
*/
|
||||
|
||||
#include "yportenv.h"
|
||||
//#include <linux/string.h>
|
||||
/* #include <linux/string.h> */
|
||||
|
||||
/*
|
||||
* Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
|
||||
*/
|
||||
#define swapcode(TYPE, parmi, parmj, n) { \
|
||||
#define swapcode(TYPE, parmi, parmj, n) do { \
|
||||
long i = (n) / sizeof (TYPE); \
|
||||
register TYPE *pi = (TYPE *) (parmi); \
|
||||
register TYPE *pj = (TYPE *) (parmj); \
|
||||
|
@ -41,28 +41,29 @@
|
|||
register TYPE t = *pi; \
|
||||
*pi++ = *pj; \
|
||||
*pj++ = t; \
|
||||
} while (--i > 0); \
|
||||
}
|
||||
} while (--i > 0); \
|
||||
} while (0)
|
||||
|
||||
#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
|
||||
es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
|
||||
es % sizeof(long) ? 2 : es == sizeof(long) ? 0 : 1;
|
||||
|
||||
static __inline void
|
||||
swapfunc(char *a, char *b, int n, int swaptype)
|
||||
{
|
||||
if (swaptype <= 1)
|
||||
swapcode(long, a, b, n)
|
||||
swapcode(long, a, b, n);
|
||||
else
|
||||
swapcode(char, a, b, n)
|
||||
swapcode(char, a, b, n);
|
||||
}
|
||||
|
||||
#define swap(a, b) \
|
||||
#define yswap(a, b) do { \
|
||||
if (swaptype == 0) { \
|
||||
long t = *(long *)(a); \
|
||||
*(long *)(a) = *(long *)(b); \
|
||||
*(long *)(b) = t; \
|
||||
} else \
|
||||
swapfunc(a, b, es, swaptype)
|
||||
swapfunc(a, b, es, swaptype); \
|
||||
} while (0)
|
||||
|
||||
#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype)
|
||||
|
||||
|
@ -70,12 +71,12 @@ static __inline char *
|
|||
med3(char *a, char *b, char *c, int (*cmp)(const void *, const void *))
|
||||
{
|
||||
return cmp(a, b) < 0 ?
|
||||
(cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a ))
|
||||
:(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c ));
|
||||
(cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a))
|
||||
: (cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c));
|
||||
}
|
||||
|
||||
#ifndef min
|
||||
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
||||
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
void
|
||||
|
@ -92,7 +93,7 @@ loop: SWAPINIT(a, es);
|
|||
for (pm = (char *)a + es; pm < (char *) a + n * es; pm += es)
|
||||
for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
|
||||
pl -= es)
|
||||
swap(pl, pl - es);
|
||||
yswap(pl, pl - es);
|
||||
return;
|
||||
}
|
||||
pm = (char *)a + (n / 2) * es;
|
||||
|
@ -107,7 +108,7 @@ loop: SWAPINIT(a, es);
|
|||
}
|
||||
pm = med3(pl, pm, pn, cmp);
|
||||
}
|
||||
swap(a, pm);
|
||||
yswap(a, pm);
|
||||
pa = pb = (char *)a + es;
|
||||
|
||||
pc = pd = (char *)a + (n - 1) * es;
|
||||
|
@ -115,7 +116,7 @@ loop: SWAPINIT(a, es);
|
|||
while (pb <= pc && (r = cmp(pb, a)) <= 0) {
|
||||
if (r == 0) {
|
||||
swap_cnt = 1;
|
||||
swap(pa, pb);
|
||||
yswap(pa, pb);
|
||||
pa += es;
|
||||
}
|
||||
pb += es;
|
||||
|
@ -123,14 +124,14 @@ loop: SWAPINIT(a, es);
|
|||
while (pb <= pc && (r = cmp(pc, a)) >= 0) {
|
||||
if (r == 0) {
|
||||
swap_cnt = 1;
|
||||
swap(pc, pd);
|
||||
yswap(pc, pd);
|
||||
pd -= es;
|
||||
}
|
||||
pc -= es;
|
||||
}
|
||||
if (pb > pc)
|
||||
break;
|
||||
swap(pb, pc);
|
||||
yswap(pb, pc);
|
||||
swap_cnt = 1;
|
||||
pb += es;
|
||||
pc -= es;
|
||||
|
@ -139,7 +140,7 @@ loop: SWAPINIT(a, es);
|
|||
for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)
|
||||
for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
|
||||
pl -= es)
|
||||
swap(pl, pl - es);
|
||||
yswap(pl, pl - es);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -148,9 +149,11 @@ loop: SWAPINIT(a, es);
|
|||
vecswap(a, pb - r, r);
|
||||
r = min((long)(pd - pc), (long)(pn - pd - es));
|
||||
vecswap(pb, pn - r, r);
|
||||
if ((r = pb - pa) > es)
|
||||
r = pb - pa;
|
||||
if (r > es)
|
||||
yaffs_qsort(a, r / es, es, cmp);
|
||||
if ((r = pd - pc) > es) {
|
||||
r = pd - pc;
|
||||
if (r > es) {
|
||||
/* Iterate rather than recurse to save stack space */
|
||||
a = pn - r;
|
||||
n = r / es;
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#ifndef __YAFFS_QSORT_H__
|
||||
#define __YAFFS_QSORT_H__
|
||||
|
||||
extern void yaffs_qsort (void *const base, size_t total_elems, size_t size,
|
||||
int (*cmp)(const void *, const void *));
|
||||
extern void yaffs_qsort(void *const base, size_t total_elems, size_t size,
|
||||
int (*cmp)(const void *, const void *));
|
||||
|
||||
#endif
|
||||
|
|
|
@ -14,16 +14,17 @@
|
|||
#include "yaffs_guts.h"
|
||||
#include "yaffs_tagscompat.h"
|
||||
#include "yaffs_ecc.h"
|
||||
#include "yaffs_getblockinfo.h"
|
||||
|
||||
static void yaffs_HandleReadDataError(yaffs_Device * dev, int chunkInNAND);
|
||||
static void yaffs_HandleReadDataError(yaffs_Device *dev, int chunkInNAND);
|
||||
#ifdef NOTYET
|
||||
static void yaffs_CheckWrittenBlock(yaffs_Device * dev, int chunkInNAND);
|
||||
static void yaffs_HandleWriteChunkOk(yaffs_Device * dev, int chunkInNAND,
|
||||
const __u8 * data,
|
||||
const yaffs_Spare * spare);
|
||||
static void yaffs_HandleUpdateChunk(yaffs_Device * dev, int chunkInNAND,
|
||||
const yaffs_Spare * spare);
|
||||
static void yaffs_HandleWriteChunkError(yaffs_Device * dev, int chunkInNAND);
|
||||
static void yaffs_CheckWrittenBlock(yaffs_Device *dev, int chunkInNAND);
|
||||
static void yaffs_HandleWriteChunkOk(yaffs_Device *dev, int chunkInNAND,
|
||||
const __u8 *data,
|
||||
const yaffs_Spare *spare);
|
||||
static void yaffs_HandleUpdateChunk(yaffs_Device *dev, int chunkInNAND,
|
||||
const yaffs_Spare *spare);
|
||||
static void yaffs_HandleWriteChunkError(yaffs_Device *dev, int chunkInNAND);
|
||||
#endif
|
||||
|
||||
static const char yaffs_countBitsTable[256] = {
|
||||
|
@ -54,13 +55,13 @@ int yaffs_CountBits(__u8 x)
|
|||
|
||||
/********** Tags ECC calculations *********/
|
||||
|
||||
void yaffs_CalcECC(const __u8 * data, yaffs_Spare * spare)
|
||||
void yaffs_CalcECC(const __u8 *data, yaffs_Spare *spare)
|
||||
{
|
||||
yaffs_ECCCalculate(data, spare->ecc1);
|
||||
yaffs_ECCCalculate(&data[256], spare->ecc2);
|
||||
}
|
||||
|
||||
void yaffs_CalcTagsECC(yaffs_Tags * tags)
|
||||
void yaffs_CalcTagsECC(yaffs_Tags *tags)
|
||||
{
|
||||
/* Calculate an ecc */
|
||||
|
||||
|
@ -74,9 +75,8 @@ void yaffs_CalcTagsECC(yaffs_Tags * tags)
|
|||
for (i = 0; i < 8; i++) {
|
||||
for (j = 1; j & 0xff; j <<= 1) {
|
||||
bit++;
|
||||
if (b[i] & j) {
|
||||
if (b[i] & j)
|
||||
ecc ^= bit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,7 +84,7 @@ void yaffs_CalcTagsECC(yaffs_Tags * tags)
|
|||
|
||||
}
|
||||
|
||||
int yaffs_CheckECCOnTags(yaffs_Tags * tags)
|
||||
int yaffs_CheckECCOnTags(yaffs_Tags *tags)
|
||||
{
|
||||
unsigned ecc = tags->ecc;
|
||||
|
||||
|
@ -115,8 +115,8 @@ int yaffs_CheckECCOnTags(yaffs_Tags * tags)
|
|||
|
||||
/********** Tags **********/
|
||||
|
||||
static void yaffs_LoadTagsIntoSpare(yaffs_Spare * sparePtr,
|
||||
yaffs_Tags * tagsPtr)
|
||||
static void yaffs_LoadTagsIntoSpare(yaffs_Spare *sparePtr,
|
||||
yaffs_Tags *tagsPtr)
|
||||
{
|
||||
yaffs_TagsUnion *tu = (yaffs_TagsUnion *) tagsPtr;
|
||||
|
||||
|
@ -132,8 +132,8 @@ static void yaffs_LoadTagsIntoSpare(yaffs_Spare * sparePtr,
|
|||
sparePtr->tagByte7 = tu->asBytes[7];
|
||||
}
|
||||
|
||||
static void yaffs_GetTagsFromSpare(yaffs_Device * dev, yaffs_Spare * sparePtr,
|
||||
yaffs_Tags * tagsPtr)
|
||||
static void yaffs_GetTagsFromSpare(yaffs_Device *dev, yaffs_Spare *sparePtr,
|
||||
yaffs_Tags *tagsPtr)
|
||||
{
|
||||
yaffs_TagsUnion *tu = (yaffs_TagsUnion *) tagsPtr;
|
||||
int result;
|
||||
|
@ -148,21 +148,20 @@ static void yaffs_GetTagsFromSpare(yaffs_Device * dev, yaffs_Spare * sparePtr,
|
|||
tu->asBytes[7] = sparePtr->tagByte7;
|
||||
|
||||
result = yaffs_CheckECCOnTags(tagsPtr);
|
||||
if (result > 0) {
|
||||
if (result > 0)
|
||||
dev->tagsEccFixed++;
|
||||
} else if (result < 0) {
|
||||
else if (result < 0)
|
||||
dev->tagsEccUnfixed++;
|
||||
}
|
||||
}
|
||||
|
||||
static void yaffs_SpareInitialise(yaffs_Spare * spare)
|
||||
static void yaffs_SpareInitialise(yaffs_Spare *spare)
|
||||
{
|
||||
memset(spare, 0xFF, sizeof(yaffs_Spare));
|
||||
}
|
||||
|
||||
static int yaffs_WriteChunkToNAND(struct yaffs_DeviceStruct *dev,
|
||||
int chunkInNAND, const __u8 * data,
|
||||
yaffs_Spare * spare)
|
||||
int chunkInNAND, const __u8 *data,
|
||||
yaffs_Spare *spare)
|
||||
{
|
||||
if (chunkInNAND < dev->startBlock * dev->nChunksPerBlock) {
|
||||
T(YAFFS_TRACE_ERROR,
|
||||
|
@ -177,9 +176,9 @@ static int yaffs_WriteChunkToNAND(struct yaffs_DeviceStruct *dev,
|
|||
|
||||
static int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev,
|
||||
int chunkInNAND,
|
||||
__u8 * data,
|
||||
yaffs_Spare * spare,
|
||||
yaffs_ECCResult * eccResult,
|
||||
__u8 *data,
|
||||
yaffs_Spare *spare,
|
||||
yaffs_ECCResult *eccResult,
|
||||
int doErrorCorrection)
|
||||
{
|
||||
int retVal;
|
||||
|
@ -252,9 +251,11 @@ static int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev,
|
|||
/* Must allocate enough memory for spare+2*sizeof(int) */
|
||||
/* for ecc results from device. */
|
||||
struct yaffs_NANDSpare nspare;
|
||||
retVal =
|
||||
dev->readChunkFromNAND(dev, chunkInNAND, data,
|
||||
(yaffs_Spare *) & nspare);
|
||||
|
||||
memset(&nspare, 0, sizeof(nspare));
|
||||
|
||||
retVal = dev->readChunkFromNAND(dev, chunkInNAND, data,
|
||||
(yaffs_Spare *) &nspare);
|
||||
memcpy(spare, &nspare, sizeof(yaffs_Spare));
|
||||
if (data && doErrorCorrection) {
|
||||
if (nspare.eccres1 > 0) {
|
||||
|
@ -302,8 +303,7 @@ static int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev,
|
|||
static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,
|
||||
int chunkInNAND)
|
||||
{
|
||||
|
||||
static int init = 0;
|
||||
static int init;
|
||||
static __u8 cmpbuf[YAFFS_BYTES_PER_CHUNK];
|
||||
static __u8 data[YAFFS_BYTES_PER_CHUNK];
|
||||
/* Might as well always allocate the larger size for */
|
||||
|
@ -331,12 +331,12 @@ static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,
|
|||
* Functions for robustisizing
|
||||
*/
|
||||
|
||||
static void yaffs_HandleReadDataError(yaffs_Device * dev, int chunkInNAND)
|
||||
static void yaffs_HandleReadDataError(yaffs_Device *dev, int chunkInNAND)
|
||||
{
|
||||
int blockInNAND = chunkInNAND / dev->nChunksPerBlock;
|
||||
|
||||
/* Mark the block for retirement */
|
||||
yaffs_GetBlockInfo(dev, blockInNAND)->needsRetiring = 1;
|
||||
yaffs_GetBlockInfo(dev, blockInNAND + dev->blockOffset)->needsRetiring = 1;
|
||||
T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,
|
||||
(TSTR("**>>Block %d marked for retirement" TENDSTR), blockInNAND));
|
||||
|
||||
|
@ -348,22 +348,22 @@ static void yaffs_HandleReadDataError(yaffs_Device * dev, int chunkInNAND)
|
|||
}
|
||||
|
||||
#ifdef NOTYET
|
||||
static void yaffs_CheckWrittenBlock(yaffs_Device * dev, int chunkInNAND)
|
||||
static void yaffs_CheckWrittenBlock(yaffs_Device *dev, int chunkInNAND)
|
||||
{
|
||||
}
|
||||
|
||||
static void yaffs_HandleWriteChunkOk(yaffs_Device * dev, int chunkInNAND,
|
||||
const __u8 * data,
|
||||
const yaffs_Spare * spare)
|
||||
static void yaffs_HandleWriteChunkOk(yaffs_Device *dev, int chunkInNAND,
|
||||
const __u8 *data,
|
||||
const yaffs_Spare *spare)
|
||||
{
|
||||
}
|
||||
|
||||
static void yaffs_HandleUpdateChunk(yaffs_Device * dev, int chunkInNAND,
|
||||
const yaffs_Spare * spare)
|
||||
static void yaffs_HandleUpdateChunk(yaffs_Device *dev, int chunkInNAND,
|
||||
const yaffs_Spare *spare)
|
||||
{
|
||||
}
|
||||
|
||||
static void yaffs_HandleWriteChunkError(yaffs_Device * dev, int chunkInNAND)
|
||||
static void yaffs_HandleWriteChunkError(yaffs_Device *dev, int chunkInNAND)
|
||||
{
|
||||
int blockInNAND = chunkInNAND / dev->nChunksPerBlock;
|
||||
|
||||
|
@ -373,8 +373,8 @@ static void yaffs_HandleWriteChunkError(yaffs_Device * dev, int chunkInNAND)
|
|||
yaffs_DeleteChunk(dev, chunkInNAND, 1, __LINE__);
|
||||
}
|
||||
|
||||
static int yaffs_VerifyCompare(const __u8 * d0, const __u8 * d1,
|
||||
const yaffs_Spare * s0, const yaffs_Spare * s1)
|
||||
static int yaffs_VerifyCompare(const __u8 *d0, const __u8 *d1,
|
||||
const yaffs_Spare *s0, const yaffs_Spare *s1)
|
||||
{
|
||||
|
||||
if (memcmp(d0, d1, YAFFS_BYTES_PER_CHUNK) != 0 ||
|
||||
|
@ -398,28 +398,35 @@ static int yaffs_VerifyCompare(const __u8 * d0, const __u8 * d1,
|
|||
}
|
||||
#endif /* NOTYET */
|
||||
|
||||
int yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(yaffs_Device * dev,
|
||||
int chunkInNAND,
|
||||
const __u8 * data,
|
||||
const yaffs_ExtendedTags *
|
||||
eTags)
|
||||
int yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(yaffs_Device *dev,
|
||||
int chunkInNAND,
|
||||
const __u8 *data,
|
||||
const yaffs_ExtendedTags *eTags)
|
||||
{
|
||||
yaffs_Spare spare;
|
||||
yaffs_Tags tags;
|
||||
|
||||
yaffs_SpareInitialise(&spare);
|
||||
|
||||
if (eTags->chunkDeleted) {
|
||||
if (eTags->chunkDeleted)
|
||||
spare.pageStatus = 0;
|
||||
} else {
|
||||
else {
|
||||
tags.objectId = eTags->objectId;
|
||||
tags.chunkId = eTags->chunkId;
|
||||
tags.byteCount = eTags->byteCount;
|
||||
|
||||
tags.byteCountLSB = eTags->byteCount & 0x3ff;
|
||||
|
||||
if (dev->nDataBytesPerChunk >= 1024)
|
||||
tags.byteCountMSB = (eTags->byteCount >> 10) & 3;
|
||||
else
|
||||
tags.byteCountMSB = 3;
|
||||
|
||||
|
||||
tags.serialNumber = eTags->serialNumber;
|
||||
|
||||
if (!dev->useNANDECC && data) {
|
||||
if (!dev->useNANDECC && data)
|
||||
yaffs_CalcECC(data, &spare);
|
||||
}
|
||||
|
||||
yaffs_LoadTagsIntoSpare(&spare, &tags);
|
||||
|
||||
}
|
||||
|
@ -427,15 +434,15 @@ int yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(yaffs_Device * dev,
|
|||
return yaffs_WriteChunkToNAND(dev, chunkInNAND, data, &spare);
|
||||
}
|
||||
|
||||
int yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(yaffs_Device * dev,
|
||||
int yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(yaffs_Device *dev,
|
||||
int chunkInNAND,
|
||||
__u8 * data,
|
||||
yaffs_ExtendedTags * eTags)
|
||||
__u8 *data,
|
||||
yaffs_ExtendedTags *eTags)
|
||||
{
|
||||
|
||||
yaffs_Spare spare;
|
||||
yaffs_Tags tags;
|
||||
yaffs_ECCResult eccResult;
|
||||
yaffs_ECCResult eccResult = YAFFS_ECC_RESULT_UNKNOWN;
|
||||
|
||||
static yaffs_Spare spareFF;
|
||||
static int init;
|
||||
|
@ -466,7 +473,11 @@ int yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(yaffs_Device * dev,
|
|||
|
||||
eTags->objectId = tags.objectId;
|
||||
eTags->chunkId = tags.chunkId;
|
||||
eTags->byteCount = tags.byteCount;
|
||||
eTags->byteCount = tags.byteCountLSB;
|
||||
|
||||
if (dev->nDataBytesPerChunk >= 1024)
|
||||
eTags->byteCount |= (((unsigned) tags.byteCountMSB) << 10);
|
||||
|
||||
eTags->serialNumber = tags.serialNumber;
|
||||
}
|
||||
}
|
||||
|
@ -497,9 +508,9 @@ int yaffs_TagsCompatabilityMarkNANDBlockBad(struct yaffs_DeviceStruct *dev,
|
|||
}
|
||||
|
||||
int yaffs_TagsCompatabilityQueryNANDBlock(struct yaffs_DeviceStruct *dev,
|
||||
int blockNo, yaffs_BlockState *
|
||||
state,
|
||||
int *sequenceNumber)
|
||||
int blockNo,
|
||||
yaffs_BlockState *state,
|
||||
__u32 *sequenceNumber)
|
||||
{
|
||||
|
||||
yaffs_Spare spare0, spare1;
|
||||
|
|
|
@ -17,24 +17,23 @@
|
|||
#define __YAFFS_TAGSCOMPAT_H__
|
||||
|
||||
#include "yaffs_guts.h"
|
||||
int yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(yaffs_Device * dev,
|
||||
int chunkInNAND,
|
||||
const __u8 * data,
|
||||
const yaffs_ExtendedTags *
|
||||
tags);
|
||||
int yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(yaffs_Device * dev,
|
||||
int chunkInNAND,
|
||||
__u8 * data,
|
||||
yaffs_ExtendedTags *
|
||||
tags);
|
||||
int yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(yaffs_Device *dev,
|
||||
int chunkInNAND,
|
||||
const __u8 *data,
|
||||
const yaffs_ExtendedTags *tags);
|
||||
int yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(yaffs_Device *dev,
|
||||
int chunkInNAND,
|
||||
__u8 *data,
|
||||
yaffs_ExtendedTags *tags);
|
||||
int yaffs_TagsCompatabilityMarkNANDBlockBad(struct yaffs_DeviceStruct *dev,
|
||||
int blockNo);
|
||||
int yaffs_TagsCompatabilityQueryNANDBlock(struct yaffs_DeviceStruct *dev,
|
||||
int blockNo, yaffs_BlockState *
|
||||
state, int *sequenceNumber);
|
||||
int blockNo,
|
||||
yaffs_BlockState *state,
|
||||
__u32 *sequenceNumber);
|
||||
|
||||
void yaffs_CalcTagsECC(yaffs_Tags * tags);
|
||||
int yaffs_CheckECCOnTags(yaffs_Tags * tags);
|
||||
void yaffs_CalcTagsECC(yaffs_Tags *tags);
|
||||
int yaffs_CheckECCOnTags(yaffs_Tags *tags);
|
||||
int yaffs_CountBits(__u8 byte);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -13,14 +13,14 @@
|
|||
|
||||
#include "yaffs_tagsvalidity.h"
|
||||
|
||||
void yaffs_InitialiseTags(yaffs_ExtendedTags * tags)
|
||||
void yaffs_InitialiseTags(yaffs_ExtendedTags *tags)
|
||||
{
|
||||
memset(tags, 0, sizeof(yaffs_ExtendedTags));
|
||||
tags->validMarker0 = 0xAAAAAAAA;
|
||||
tags->validMarker1 = 0x55555555;
|
||||
}
|
||||
|
||||
int yaffs_ValidateTags(yaffs_ExtendedTags * tags)
|
||||
int yaffs_ValidateTags(yaffs_ExtendedTags *tags)
|
||||
{
|
||||
return (tags->validMarker0 == 0xAAAAAAAA &&
|
||||
tags->validMarker1 == 0x55555555);
|
||||
|
|
|
@ -19,6 +19,6 @@
|
|||
|
||||
#include "yaffs_guts.h"
|
||||
|
||||
void yaffs_InitialiseTags(yaffs_ExtendedTags * tags);
|
||||
int yaffs_ValidateTags(yaffs_ExtendedTags * tags);
|
||||
void yaffs_InitialiseTags(yaffs_ExtendedTags *tags);
|
||||
int yaffs_ValidateTags(yaffs_ExtendedTags *tags);
|
||||
#endif
|
||||
|
|
|
@ -17,17 +17,28 @@
|
|||
#ifndef __YPORTENV_H__
|
||||
#define __YPORTENV_H__
|
||||
|
||||
/*
|
||||
* Define the MTD version in terms of Linux Kernel versions
|
||||
* This allows yaffs to be used independantly of the kernel
|
||||
* as well as with it.
|
||||
*/
|
||||
|
||||
#define MTD_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c))
|
||||
|
||||
#if defined CONFIG_YAFFS_WINCE
|
||||
|
||||
#include "ywinceenv.h"
|
||||
|
||||
#elif defined __KERNEL__
|
||||
#elif defined __KERNEL__
|
||||
|
||||
#include "moduleconfig.h"
|
||||
|
||||
/* Linux kernel */
|
||||
|
||||
#include <linux/version.h>
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
|
||||
#define MTD_VERSION_CODE LINUX_VERSION_CODE
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))
|
||||
#include <linux/config.h>
|
||||
#endif
|
||||
#include <linux/kernel.h>
|
||||
|
@ -40,12 +51,13 @@
|
|||
#define YCHAR char
|
||||
#define YUCHAR unsigned char
|
||||
#define _Y(x) x
|
||||
#define yaffs_strcpy(a,b) strcpy(a,b)
|
||||
#define yaffs_strncpy(a,b,c) strncpy(a,b,c)
|
||||
#define yaffs_strncmp(a,b,c) strncmp(a,b,c)
|
||||
#define yaffs_strlen(s) strlen(s)
|
||||
#define yaffs_sprintf sprintf
|
||||
#define yaffs_toupper(a) toupper(a)
|
||||
#define yaffs_strcat(a, b) strcat(a, b)
|
||||
#define yaffs_strcpy(a, b) strcpy(a, b)
|
||||
#define yaffs_strncpy(a, b, c) strncpy(a, b, c)
|
||||
#define yaffs_strncmp(a, b, c) strncmp(a, b, c)
|
||||
#define yaffs_strlen(s) strlen(s)
|
||||
#define yaffs_sprintf sprintf
|
||||
#define yaffs_toupper(a) toupper(a)
|
||||
|
||||
#define Y_INLINE inline
|
||||
|
||||
|
@ -53,19 +65,19 @@
|
|||
#define YAFFS_LOSTNFOUND_PREFIX "obj"
|
||||
|
||||
/* #define YPRINTF(x) printk x */
|
||||
#define YMALLOC(x) kmalloc(x,GFP_KERNEL)
|
||||
#define YMALLOC(x) kmalloc(x, GFP_NOFS)
|
||||
#define YFREE(x) kfree(x)
|
||||
#define YMALLOC_ALT(x) vmalloc(x)
|
||||
#define YFREE_ALT(x) vfree(x)
|
||||
#define YMALLOC_DMA(x) YMALLOC(x)
|
||||
|
||||
// KR - added for use in scan so processes aren't blocked indefinitely.
|
||||
/* KR - added for use in scan so processes aren't blocked indefinitely. */
|
||||
#define YYIELD() schedule()
|
||||
|
||||
#define YAFFS_ROOT_MODE 0666
|
||||
#define YAFFS_LOSTNFOUND_MODE 0666
|
||||
|
||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
|
||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
|
||||
#define Y_CURRENT_TIME CURRENT_TIME.tv_sec
|
||||
#define Y_TIME_CONVERT(x) (x).tv_sec
|
||||
#else
|
||||
|
@ -73,11 +85,12 @@
|
|||
#define Y_TIME_CONVERT(x) (x)
|
||||
#endif
|
||||
|
||||
#define yaffs_SumCompare(x,y) ((x) == (y))
|
||||
#define yaffs_strcmp(a,b) strcmp(a,b)
|
||||
#define yaffs_SumCompare(x, y) ((x) == (y))
|
||||
#define yaffs_strcmp(a, b) strcmp(a, b)
|
||||
|
||||
#define TENDSTR "\n"
|
||||
#define TSTR(x) KERN_WARNING x
|
||||
#define TCONT(x) x
|
||||
#define TOUT(p) printk p
|
||||
|
||||
#define yaffs_trace(mask, fmt, args...) \
|
||||
|
@ -90,6 +103,8 @@
|
|||
|
||||
#elif defined CONFIG_YAFFS_DIRECT
|
||||
|
||||
#define MTD_VERSION_CODE MTD_VERSION(2, 6, 22)
|
||||
|
||||
/* Direct interface */
|
||||
#include "ydirectenv.h"
|
||||
|
||||
|
@ -111,11 +126,12 @@
|
|||
#define YCHAR char
|
||||
#define YUCHAR unsigned char
|
||||
#define _Y(x) x
|
||||
#define yaffs_strcpy(a,b) strcpy(a,b)
|
||||
#define yaffs_strncpy(a,b,c) strncpy(a,b,c)
|
||||
#define yaffs_strlen(s) strlen(s)
|
||||
#define yaffs_sprintf sprintf
|
||||
#define yaffs_toupper(a) toupper(a)
|
||||
#define yaffs_strcat(a, b) strcat(a, b)
|
||||
#define yaffs_strcpy(a, b) strcpy(a, b)
|
||||
#define yaffs_strncpy(a, b, c) strncpy(a, b, c)
|
||||
#define yaffs_strlen(s) strlen(s)
|
||||
#define yaffs_sprintf sprintf
|
||||
#define yaffs_toupper(a) toupper(a)
|
||||
|
||||
#define Y_INLINE inline
|
||||
|
||||
|
@ -133,8 +149,8 @@
|
|||
#define YAFFS_ROOT_MODE 0666
|
||||
#define YAFFS_LOSTNFOUND_MODE 0666
|
||||
|
||||
#define yaffs_SumCompare(x,y) ((x) == (y))
|
||||
#define yaffs_strcmp(a,b) strcmp(a,b)
|
||||
#define yaffs_SumCompare(x, y) ((x) == (y))
|
||||
#define yaffs_strcmp(a, b) strcmp(a, b)
|
||||
|
||||
#else
|
||||
/* Should have specified a configuration type */
|
||||
|
@ -178,10 +194,10 @@ extern unsigned int yaffs_wr_attempts;
|
|||
#define YAFFS_TRACE_ALWAYS 0xF0000000
|
||||
|
||||
|
||||
#define T(mask,p) do{ if((mask) & (yaffs_traceMask | YAFFS_TRACE_ALWAYS)) TOUT(p);} while(0)
|
||||
#define T(mask, p) do { if ((mask) & (yaffs_traceMask | YAFFS_TRACE_ALWAYS)) TOUT(p); } while (0)
|
||||
|
||||
#ifndef CONFIG_YAFFS_WINCE
|
||||
#define YBUG() T(YAFFS_TRACE_BUG,(TSTR("==>> yaffs bug: " __FILE__ " %d" TENDSTR),__LINE__))
|
||||
#ifndef YBUG
|
||||
#define YBUG() do {T(YAFFS_TRACE_BUG, (TSTR("==>> yaffs bug: " __FILE__ " %d" TENDSTR), __LINE__)); } while (0)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue