summaryrefslogtreecommitdiff
path: root/fs/yaffs2/yaffs_guts.h
blob: 1f75efd09810e59100e2a47d851311598c26261e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
/*
 * 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_GUTS_H__
#define __YAFFS_GUTS_H__

#include "devextras.h"
#include "yportenv.h"

#define YAFFS_OK	1
#define YAFFS_FAIL  0

/* Give us a  Y=0x59,
 * Give us an A=0x41,
 * Give us an FF=0xFF
 * Give us an S=0x53
 * And what have we got...
 */
#define YAFFS_MAGIC			0x5941FF53

#define YAFFS_NTNODES_LEVEL0	  	16
#define YAFFS_TNODES_LEVEL0_BITS	4
#define YAFFS_TNODES_LEVEL0_MASK	0xf

#define YAFFS_NTNODES_INTERNAL 		(YAFFS_NTNODES_LEVEL0 / 2)
#define YAFFS_TNODES_INTERNAL_BITS 	(YAFFS_TNODES_LEVEL0_BITS - 1)
#define YAFFS_TNODES_INTERNAL_MASK	0x7
#define YAFFS_TNODES_MAX_LEVEL		6

#ifndef CONFIG_YAFFS_NO_YAFFS1
#define YAFFS_BYTES_PER_SPARE		16
#define YAFFS_BYTES_PER_CHUNK		512
#define YAFFS_CHUNK_SIZE_SHIFT		9
#define YAFFS_CHUNKS_PER_BLOCK		32
#define YAFFS_BYTES_PER_BLOCK		(YAFFS_CHUNKS_PER_BLOCK*YAFFS_BYTES_PER_CHUNK)
#endif

#define YAFFS_MIN_YAFFS2_CHUNK_SIZE 	1024
#define YAFFS_MIN_YAFFS2_SPARE_SIZE	32

#define YAFFS_MAX_CHUNK_ID		0x000FFFFF

#define YAFFS_UNUSED_OBJECT_ID		0x0003FFFF

#define YAFFS_ALLOCATION_NOBJECTS	100
#define YAFFS_ALLOCATION_NTNODES	100
#define YAFFS_ALLOCATION_NLINKS		100

#define YAFFS_NOBJECT_BUCKETS		256


#define YAFFS_OBJECT_SPACE		0x40000

#define YAFFS_CHECKPOINT_VERSION 	3

#ifdef CONFIG_YAFFS_UNICODE
#define YAFFS_MAX_NAME_LENGTH		127
#define YAFFS_MAX_ALIAS_LENGTH		79
#else
#define YAFFS_MAX_NAME_LENGTH		255
#define YAFFS_MAX_ALIAS_LENGTH		159
#endif

#define YAFFS_SHORT_NAME_LENGTH		15

/* Some special object ids for pseudo objects */
#define YAFFS_OBJECTID_ROOT		1
#define YAFFS_OBJECTID_LOSTNFOUND	2
#define YAFFS_OBJECTID_UNLINKED		3
#define YAFFS_OBJECTID_DELETED		4

/* Sseudo object ids for checkpointing */
#define YAFFS_OBJECTID_SB_HEADER	0x10
#define YAFFS_OBJECTID_CHECKPOINT_DATA	0x20
#define YAFFS_SEQUENCE_CHECKPOINT_DATA  0x21

/* */

#define YAFFS_MAX_SHORT_OP_CACHES	20

#define YAFFS_N_TEMP_BUFFERS		4

/* 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.
 * Default to something in the order of 5 to 10 blocks worth of chunks.
 */
#define YAFFS_WR_ATTEMPTS		(5*64)

/* Sequence numbers are used in YAFFS2 to determine block allocation order.
 * The range is limited slightly to help distinguish bad numbers from good.
 * This also allows us to perhaps in the future use special numbers for
 * special purposes.
 * EFFFFF00 allows the allocation of 8 blocks per second (~1Mbytes) for 15 years,
 * and is a larger number than the lifetime of a 2GB device.
 */
#define YAFFS_LOWEST_SEQUENCE_NUMBER	0x00001000
#define YAFFS_HIGHEST_SEQUENCE_NUMBER	0xEFFFFF00

/* ChunkCache is used for short read/write operations.*/
typedef struct {
	struct yaffs_ObjectStruct *object;
	int chunkId;
	int lastUse;
	int dirty;
	int nBytes;		/* Only valid if the cache is dirty */
	int locked;		/* Can't push out or flush while locked. */
#ifdef CONFIG_YAFFS_YAFFS2
	__u8 *data;
#else
	__u8 data[YAFFS_BYTES_PER_CHUNK];
#endif
} yaffs_ChunkCache;



/* Tags structures in RAM
 * NB This uses bitfield. Bitfields should not straddle a u32 boundary otherwise
 * the structure size will get blown out.
 */

#ifndef CONFIG_YAFFS_NO_YAFFS1
typedef struct {
	unsigned chunkId:20;
	unsigned serialNumber:2;
	unsigned byteCount:10;
	unsigned objectId:18;
	unsigned ecc:12;
	unsigned unusedStuff:2;

} yaffs_Tags;

typedef union {
	yaffs_Tags asTags;
	__u8 asBytes[8];
} yaffs_TagsUnion;

#endif

/* Stuff used for extended tags in YAFFS2 */

typedef enum {
	YAFFS_ECC_RESULT_UNKNOWN,
	YAFFS_ECC_RESULT_NO_ERROR,
	YAFFS_ECC_RESULT_FIXED,
	YAFFS_ECC_RESULT_UNFIXED
} yaffs_ECCResult;

typedef enum {
	YAFFS_OBJECT_TYPE_UNKNOWN,
	YAFFS_OBJECT_TYPE_FILE,
	YAFFS_OBJECT_TYPE_SYMLINK,
	YAFFS_OBJECT_TYPE_DIRECTORY,
	YAFFS_OBJECT_TYPE_HARDLINK,
	YAFFS_OBJECT_TYPE_SPECIAL
} yaffs_ObjectType;

#define YAFFS_OBJECT_TYPE_MAX YAFFS_OBJECT_TYPE_SPECIAL

typedef struct {

	unsigned validMarker0;
	unsigned chunkUsed;	/*  Status of the chunk: used or unused */
	unsigned objectId;	/* If 0 then this is not part of an object (unused) */
	unsigned chunkId;	/* If 0 then this is a header, else a data chunk */
	unsigned byteCount;	/* Only valid for data chunks */

	/* The following stuff only has meaning when we read */
	yaffs_ECCResult eccResult;
	unsigned blockBad;

	/* YAFFS 1 stuff */
	unsigned chunkDeleted;	/* The chunk is marked deleted */
	unsigned serialNumber;	/* Yaffs1 2-bit serial number */

	/* YAFFS2 stuff */
	unsigned sequenceNumber;	/* The sequence number of this block */

	/* Extra info if this is an object header (YAFFS2 only) */

	unsigned extraHeaderInfoAvailable;	/* There is extra info available if this is not zero */
	unsigned extraParentObjectId;	/* The parent object */
	unsigned extraIsShrinkHeader;	/* Is it a shrink header? */
	unsigned extraShadows;		/* Does this shadow another object? */

	yaffs_ObjectType extraObjectType;	/* What object type? */

	unsigned extraFileLength;		/* Length if it is a file */
	unsigned extraEquivalentObjectId;	/* Equivalent object Id if it is a hard link */

	unsigned validMarker1;

} yaffs_ExtendedTags;

/* Spare structure for YAFFS1 */
typedef struct {
	__u8 tagByte0;
	__u8 tagByte1;
	__u8 tagByte2;
	__u8 tagByte3;
	__u8 pageStatus;	/* set to 0 to delete the chunk */
	__u8 blockStatus;
	__u8 tagByte4;
	__u8 tagByte5;
	__u8 ecc1[3];
	__u8 tagByte6;
	__u8 tagByte7;
	__u8 ecc2[3];
} yaffs_Spare;

/*Special structure for passing through to mtd */
struct yaffs_NANDSpare {
	yaffs_Spare spare;
	int eccres1;
	int eccres2;
};

/* Block data in RAM */

typedef enum {
	YAFFS_BLOCK_STATE_UNKNOWN = 0,

	YAFFS_BLOCK_STATE_SCANNING,
	YAFFS_BLOCK_STATE_NEEDS_SCANNING,
	/* The block might have something on it (ie it is allocating or full, perhaps empty)
	 * but it needs to be scanned to determine its true state.
	 * This state is only valid during yaffs_Scan.
	 * NB We tolerate empty because the pre-scanner might be incapable of deciding
	 * However, if this state is returned on a YAFFS2 device, then we expect a sequence number
	 */

	YAFFS_BLOCK_STATE_EMPTY,
	/* This block is empty */

	YAFFS_BLOCK_STATE_ALLOCATING,
	/* This block is partially allocated.
	 * At least one page holds valid data.
	 * This is the one currently being used for page
	 * allocation. Should never be more than one of these
	 */

	YAFFS_BLOCK_STATE_FULL,
	/* All the pages in this block have been allocated.
	 */

	YAFFS_BLOCK_STATE_DIRTY,
	/* All pages have been allocated and deleted.
	 * Erase me, reuse me.
	 */

	YAFFS_BLOCK_STATE_CHECKPOINT,
	/* This block is assigned to holding checkpoint data.
	 */

	YAFFS_BLOCK_STATE_COLLECTING,
	/* This block is being garbage collected */

	YAFFS_BLOCK_STATE_DEAD
	/* This block has failed and is not in use */
} yaffs_BlockState;

#define	YAFFS_NUMBER_OF_BLOCK_STATES (YAFFS_BLOCK_STATE_DEAD + 1)


typedef struct {

	int softDeletions:10;	/* number of soft deleted pages */
	int pagesInUse:10;	/* number of pages in use */
	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.
				   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 */

#ifdef CONFIG_YAFFS_YAFFS2
	__u32 hasShrinkHeader:1; /* This block has at least one shrink object header */
	__u32 sequenceNumber;	 /* block sequence number for yaffs2 */
#endif

} yaffs_BlockInfo;

/* -------------------------- Object structure -------------------------------*/
/* This is the object structure as stored on NAND */

typedef struct {
	yaffs_ObjectType type;

	/* Apply to everything  */
	int parentObjectId;
	__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 */

#ifdef CONFIG_YAFFS_WINCE
	__u32 notForWinCE[5];
#else
	__u32 yst_uid;
	__u32 yst_gid;
	__u32 yst_atime;
	__u32 yst_mtime;
	__u32 yst_ctime;
#endif

	/* File size  applies to files only */
	int fileSize;

	/* Equivalent object id applies to hard links only. */
	int equivalentObjectId;

	/* Alias is for symlinks only. */
	YCHAR alias[YAFFS_MAX_ALIAS_LENGTH + 1];

	__u32 yst_rdev;		/* device stuff for block and char devices (major/min) */

#ifdef CONFIG_YAFFS_WINCE
	__u32 win_ctime[2];
	__u32 win_atime[2];
	__u32 win_mtime[2];
	__u32 roomToGrow[4];
#else
	__u32 roomToGrow[10];
#endif

	int shadowsObject;	/* This object header shadows the specified object if > 0 */

	/* isShrink applies to object headers written when we shrink the file (ie resize) */
	__u32 isShrink;

} yaffs_ObjectHeader;

/*--------------------------- Tnode -------------------------- */

union yaffs_Tnode_union {
#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG
	union yaffs_Tnode_union *internal[YAFFS_NTNODES_INTERNAL + 1];
#else
	union yaffs_Tnode_union *internal[YAFFS_NTNODES_INTERNAL];
#endif
/*	__u16 level0[YAFFS_NTNODES_LEVEL0]; */

};

typedef union yaffs_Tnode_union yaffs_Tnode;

struct yaffs_TnodeList_struct {
	struct yaffs_TnodeList_struct *next;
	yaffs_Tnode *tnodes;
};

typedef struct yaffs_TnodeList_struct yaffs_TnodeList;

/*------------------------  Object -----------------------------*/
/* An object can be one of:
 * - a directory (no data, has children links
 * - a regular file (data.... not prunes :->).
 * - a symlink [symbolic link] (the alias).
 * - a hard link
 */

typedef struct {
	__u32 fileSize;
	__u32 scannedFileSize;
	__u32 shrinkSize;
	int topLevel;
	yaffs_Tnode *top;
} yaffs_FileStructure;

typedef struct {
	struct list_head children;	/* list of child links */
} yaffs_DirectoryStructure;

typedef struct {
	YCHAR *alias;
} yaffs_SymLinkStructure;

typedef struct {
	struct yaffs_ObjectStruct *equivalentObject;
	__u32 equivalentObjectId;
} yaffs_HardLinkStructure;

typedef union {
	yaffs_FileStructure fileVariant;
	yaffs_DirectoryStructure directoryVariant;
	yaffs_SymLinkStructure symLinkVariant;
	yaffs_HardLinkStructure hardLinkVariant;
} yaffs_ObjectVariant;

struct yaffs_ObjectStruct {
	__u8 deleted:1;		/* This should only apply to unlinked files. */
	__u8 softDeleted:1;	/* it has also been soft deleted */
	__u8 unlinked:1;	/* An unlinked file. The file should be in the unlinked directory.*/
	__u8 fake:1;		/* A fake object has no presence on NAND. */
	__u8 renameAllowed:1;	/* Some objects are not allowed to be renamed. */
	__u8 unlinkAllowed:1;
	__u8 dirty:1;		/* the object needs to be written to flash */
	__u8 valid:1;		/* When the file system is being loaded up, this
				 * object might be created before the data
				 * is available (ie. file data records appear before the header).
				 */
	__u8 lazyLoaded:1;	/* This object has been lazy loaded and is missing some detail */

	__u8 deferedFree:1;	/* For Linux kernel. Object is removed from NAND, but is
				 * still in the inode cache. Free of object is defered.
				 * until the inode is released.
				 */

	__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 list_head hashLink;	/* list of objects in this hash bucket */

	struct list_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;

	/* Where's my object header in NAND? */
	int chunkId;

	int nDataChunks;	/* Number of data chunks attached to the file. */

	__u32 objectId;		/* the object id value */

	__u32 yst_mode;

#ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM
	YCHAR shortName[YAFFS_SHORT_NAME_LENGTH + 1];
#endif

/* XXX U-BOOT XXX */
/* #ifndef __KERNEL__ */
	__u32 inUse;
/* #endif */

#ifdef CONFIG_YAFFS_WINCE
	__u32 win_ctime[2];
	__u32 win_mtime[2];
	__u32 win_atime[2];
#else
	__u32 yst_uid;
	__u32 yst_gid;
	__u32 yst_atime;
	__u32 yst_mtime;
	__u32 yst_ctime;
#endif

	__u32 yst_rdev;

/* XXX U-BOOT XXX */
/* #ifndef __KERNEL__ */
	struct inode *myInode;
/* #endif */

	yaffs_ObjectType variantType;

	yaffs_ObjectVariant variant;

};

typedef struct yaffs_ObjectStruct yaffs_Object;

struct yaffs_ObjectList_struct {
	yaffs_Object *objects;
	struct yaffs_ObjectList_struct *next;
};

typedef struct yaffs_ObjectList_struct yaffs_ObjectList;

typedef struct {
	struct list_head list;
	int count;
} yaffs_ObjectBucket;


/* yaffs_CheckpointObject holds the definition of an object as dumped
 * by checkpointing.
 */

typedef struct {
	int structType;
	__u32 objectId;
	__u32 parentId;
	int chunkId;

	yaffs_ObjectType variantType:3;
	__u8 deleted:1;
	__u8 softDeleted:1;
	__u8 unlinked:1;
	__u8 fake:1;
	__u8 renameAllowed:1;
	__u8 unlinkAllowed:1;
	__u8 serial;

	int nDataChunks;
	__u32 fileSizeOrEquivalentObjectId;

}yaffs_CheckpointObject;

/*--------------------- Temporary buffers ----------------
 *
 * These are chunk-sized working buffers. Each device has a few
 */

typedef struct {
	__u8 *buffer;
	int line;	/* track from whence this buffer was allocated */
	int maxLine;
} yaffs_TempBuffer;

/*----------------- Device ---------------------------------*/

struct yaffs_DeviceStruct {
	struct list_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 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 */
				/* reserved blocks on NOR and RAM. */


	/* 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 nShortOpCaches;	/* If <= 0, then short op caching is disabled, else
				 * the number of short op caches (don't use too many)
				 */

	int useHeaderFileSize;	/* Flag to determine if we should use file sizes from the header */

	int useNANDECC;		/* Flag to decide whether or not to use NANDECC */

	void *genericDevice;	/* Pointer to device context
				 * On an mtd this holds the mtd pointer.
				 */
	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);

#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);
#endif

	int isYaffs2;

	/* The removeObjectCallback function must be supplied by OS flavours that
	 * need it. The Linux kernel does not use this, but yaffs direct does use
	 * it to implement the faster readdir
	 */
	void (*removeObjectCallback)(struct yaffs_ObjectStruct *obj);

	/* Callback to mark the superblock dirsty */
	void (*markSuperBlockDirty)(void * superblock);

	int wideTnodesDisabled; /* Set to disable wide tnodes */


	/* End of stuff that must be set before initialisation. */

	/* Checkpoint control. Can be set before or after initialisation */
	__u8 skipCheckpointRead;
	__u8 skipCheckpointWrite;

	/* Runtime parameters. Set up by YAFFS. */

	__u16 chunkGroupBits;	/* 0 for devices <= 32MB. else log2(nchunks) - 16 */
	__u16 chunkGroupSize;	/* == 2^^chunkGroupBits */

	/* Stuff to support wide tnodes */
	__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;


/* XXX U-BOOT XXX */
#if 0
#ifndef __KERNEL__

	struct semaphore sem;	/* Semaphore for waiting on erasure.*/
	struct semaphore grossLock;	/* Gross locking semaphore */
	void (*putSuperFunc) (struct super_block * sb);
#endif
#endif
	__u8 *spareBuffer;	/* For mtdif2 use. Don't know the size of the buffer
				 * at compile time so we have to allocate it.
				 */

	int isMounted;

	int isCheckpointed;


	/* Stuff to support block offsetting to support start block zero */
	int internalStartBlock;
	int internalEndBlock;
	int blockOffset;
	int chunkOffset;


	/* Runtime checkpointing stuff */
	int checkpointPageSequence;   /* running sequence number of checkpoint pages */
	int checkpointByteCount;
	int checkpointByteOffset;
	__u8 *checkpointBuffer;
	int checkpointOpenForWrite;
	int blocksInCheckpoint;
	int checkpointCurrentChunk;
	int checkpointCurrentBlock;
	int checkpointNextBlock;
	int *checkpointBlockList;
	int checkpointMaxBlocks;
	__u32 checkpointSum;
	__u32 checkpointXor;

	/* Block Info */
	yaffs_BlockInfo *blockInfo;
	__u8 *chunkBits;	/* bitmap of chunks in use */
	unsigned blockInfoAlt:1;	/* was allocated using alternative strategy */
	unsigned chunkBitsAlt:1;	/* was allocated using alternative strategy */
	int chunkBitmapStride;	/* Number of bytes of chunkBits per block.
				 * Must be consistent with nChunksPerBlock.
				 */

	int nErasedBlocks;
	int allocationBlock;	/* Current block being allocated off */
	__u32 allocationPage;
	int allocationBlockFinder;	/* Used to search for next allocation block */

	/* Runtime state */
	int nTnodesCreated;
	yaffs_Tnode *freeTnodes;
	int nFreeTnodes;
	yaffs_TnodeList *allocatedTnodeList;

	int isDoingGC;

	int nObjectsCreated;
	yaffs_Object *freeObjects;
	int nFreeObjects;

	yaffs_ObjectList *allocatedObjectList;

	yaffs_ObjectBucket objectBucket[YAFFS_NOBJECT_BUCKETS];

	int nFreeChunks;

	int currentDirtyChecker;	/* Used to find current dirtiest block */

	__u32 *gcCleanupList;	/* objects to delete at the end of a GC. */
	int nonAggressiveSkip;	/* GC state/mode */

	/* Statistcs */
	int nPageWrites;
	int nPageReads;
	int nBlockErasures;
	int nErasureFailures;
	int nGCCopies;
	int garbageCollections;
	int passiveGarbageCollections;
	int nRetriedWrites;
	int nRetiredBlocks;
	int eccFixed;
	int eccUnfixed;
	int tagsEccFixed;
	int tagsEccUnfixed;
	int nDeletions;
	int nUnmarkedDeletions;

	int hasPendingPrioritisedGCs; /* We think this device might have pending prioritised gcs */

	/* Special directories */
	yaffs_Object *rootDir;
	yaffs_Object *lostNFoundDir;

	/* Buffer areas for storing data to recover from write failures TODO
	 *      __u8            bufferedData[YAFFS_CHUNKS_PER_BLOCK][YAFFS_BYTES_PER_CHUNK];
	 *      yaffs_Spare bufferedSpare[YAFFS_CHUNKS_PER_BLOCK];
	 */

	int bufferedBlock;	/* Which block is buffered here? */
	int doingBufferedBlockRewrite;

	yaffs_ChunkCache *srCache;
	int srLastUse;

	int cacheHits;

	/* Stuff for background deletion and unlinked files.*/
	yaffs_Object *unlinkedDir;	/* Directory where unlinked and deleted files live. */
	yaffs_Object *deletedDir;	/* Directory where deleted objects are sent to disappear. */
	yaffs_Object *unlinkedDeletion;	/* Current file being background deleted.*/
	int nDeletedFiles;		/* Count of files awaiting deletion;*/
	int nUnlinkedFiles;		/* Count of unlinked files. */
	int nBackgroundDeletions;	/* Count of background deletions. */


	yaffs_TempBuffer tempBuffer[YAFFS_N_TEMP_BUFFERS];
	int maxTemp;
	int unmanagedTempAllocations;
	int unmanagedTempDeallocations;

	/* yaffs2 runtime stuff */
	unsigned sequenceNumber;	/* Sequence number of currently allocating block */
	unsigned oldestDirtySequence;

};

typedef struct yaffs_DeviceStruct yaffs_Device;

/* The static layout of bllock usage etc is stored in the super block header */
typedef struct {
	int StructType;
	int version;
	int checkpointStartBlock;
	int checkpointEndBlock;
	int startBlock;
	int endBlock;
	int rfu[100];
} yaffs_SuperBlockHeader;

/* The CheckpointDevice structure holds the device information that changes at runtime and
 * must be preserved over unmount/mount cycles.
 */
typedef struct {
	int structType;
	int nErasedBlocks;
	int allocationBlock;	/* Current block being allocated off */
	__u32 allocationPage;
	int nFreeChunks;

	int nDeletedFiles;		/* Count of files awaiting deletion;*/
	int nUnlinkedFiles;		/* Count of unlinked files. */
	int nBackgroundDeletions;	/* Count of background deletions. */

	/* yaffs2 runtime stuff */
	unsigned sequenceNumber;	/* Sequence number of currently allocating block */
	unsigned oldestDirtySequence;

} yaffs_CheckpointDevice;


typedef struct {
    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_GetNumberOfFreeChunks(yaffs_Device * dev);

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_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);

/* 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);

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);

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,
				   int (*fn) (yaffs_Object *));

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_GetEquivalentObject(yaffs_Object * obj);

/* Symlink operations */
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);

/* Special inodes (fifos, sockets and devices) */
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);

#ifdef CONFIG_YAFFS_WINCE
/* CONFIG_YAFFS_WINCE special stuff */
void yfsd_WinFileTimeNow(__u32 target[2]);
#endif

/* XXX U-BOOT XXX */
#if 0
#ifndef __KERNEL__
void yaffs_HandleDeferedFree(yaffs_Object * obj);
#endif
#endif

/* Debug dump  */
int yaffs_DumpObject(yaffs_Object * obj);

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_HandleChunkError(yaffs_Device *dev, yaffs_BlockInfo *bi);

#endif