Add Linux 2.6.29 support
[yaffs2.git] / yaffs_packedtags2.c
1 /*
2  * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
3  *
4  * Copyright (C) 2002-2007 Aleph One Ltd.
5  *   for Toby Churchill Ltd and Brightstar Engineering
6  *
7  * Created by Charles Manning <charles@aleph1.co.uk>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License version 2 as
11  * published by the Free Software Foundation.
12  */
13
14 #include "yaffs_packedtags2.h"
15 #include "yportenv.h"
16 #include "yaffs_tagsvalidity.h"
17
18 /* This code packs a set of extended tags into a binary structure for
19  * NAND storage
20  */
21
22 /* Some of the information is "extra" struff which can be packed in to
23  * speed scanning
24  * This is defined by having the EXTRA_HEADER_INFO_FLAG set.
25  */
26
27 /* Extra flags applied to chunkId */
28
29 #define EXTRA_HEADER_INFO_FLAG  0x80000000
30 #define EXTRA_SHRINK_FLAG       0x40000000
31 #define EXTRA_SHADOWS_FLAG      0x20000000
32 #define EXTRA_SPARE_FLAGS       0x10000000
33
34 #define ALL_EXTRA_FLAGS         0xF0000000
35
36 /* Also, the top 4 bits of the object Id are set to the object type. */
37 #define EXTRA_OBJECT_TYPE_SHIFT (28)
38 #define EXTRA_OBJECT_TYPE_MASK  ((0x0F) << EXTRA_OBJECT_TYPE_SHIFT)
39
40
41 static void yaffs_DumpPackedTags2TagsPart(const yaffs_PackedTags2TagsPart * ptt)
42 {
43         T(YAFFS_TRACE_MTD,
44           (TSTR("packed tags obj %d chunk %d byte %d seq %d" TENDSTR),
45            ptt->objectId, ptt->chunkId, ptt->byteCount,
46            ptt->sequenceNumber));
47 }
48 static void yaffs_DumpPackedTags2(const yaffs_PackedTags2 * pt)
49 {
50         yaffs_DumpPackedTags2TagsPart(&pt->t);
51 }
52
53 static void yaffs_DumpTags2(const yaffs_ExtendedTags * t)
54 {
55         T(YAFFS_TRACE_MTD,
56           (TSTR
57            ("ext.tags eccres %d blkbad %d chused %d obj %d chunk%d byte %d del %d ser %d seq %d"
58             TENDSTR), t->eccResult, t->blockBad, t->chunkUsed, t->objectId,
59            t->chunkId, t->byteCount, t->chunkDeleted, t->serialNumber,
60            t->sequenceNumber));
61
62 }
63
64 void yaffs_PackTags2TagsPart(yaffs_PackedTags2TagsPart * ptt, const yaffs_ExtendedTags * t)
65 {
66         ptt->chunkId = t->chunkId;
67         ptt->sequenceNumber = t->sequenceNumber;
68         ptt->byteCount = t->byteCount;
69         ptt->objectId = t->objectId;
70
71         if (t->chunkId == 0 && t->extraHeaderInfoAvailable) {
72                 /* Store the extra header info instead */
73                 /* We save the parent object in the chunkId */
74                 ptt->chunkId = EXTRA_HEADER_INFO_FLAG
75                         | t->extraParentObjectId;
76                 if (t->extraIsShrinkHeader) {
77                         ptt->chunkId |= EXTRA_SHRINK_FLAG;
78                 }
79                 if (t->extraShadows) {
80                         ptt->chunkId |= EXTRA_SHADOWS_FLAG;
81                 }
82
83                 ptt->objectId &= ~EXTRA_OBJECT_TYPE_MASK;
84                 ptt->objectId |=
85                     (t->extraObjectType << EXTRA_OBJECT_TYPE_SHIFT);
86
87                 if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) {
88                         ptt->byteCount = t->extraEquivalentObjectId;
89                 } else if (t->extraObjectType == YAFFS_OBJECT_TYPE_FILE) {
90                         ptt->byteCount = t->extraFileLength;
91                 } else {
92                         ptt->byteCount = 0;
93                 }
94         }
95
96         yaffs_DumpPackedTags2TagsPart(ptt);
97         yaffs_DumpTags2(t);
98 }
99
100
101 void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags * t)
102 {
103         yaffs_PackTags2TagsPart(&pt->t,t);
104
105 #ifndef YAFFS_IGNORE_TAGS_ECC
106         {
107                 yaffs_ECCCalculateOther((unsigned char *)&pt->t,
108                                         sizeof(yaffs_PackedTags2TagsPart),
109                                         &pt->ecc);
110         }
111 #endif
112 }
113
114
115 void yaffs_UnpackTags2TagsPart(yaffs_ExtendedTags * t, yaffs_PackedTags2TagsPart * ptt)
116 {
117
118         memset(t, 0, sizeof(yaffs_ExtendedTags));
119
120         yaffs_InitialiseTags(t);
121
122         if (ptt->sequenceNumber != 0xFFFFFFFF) {
123                 t->blockBad = 0;
124                 t->chunkUsed = 1;
125                 t->objectId = ptt->objectId;
126                 t->chunkId = ptt->chunkId;
127                 t->byteCount = ptt->byteCount;
128                 t->chunkDeleted = 0;
129                 t->serialNumber = 0;
130                 t->sequenceNumber = ptt->sequenceNumber;
131
132                 /* Do extra header info stuff */
133
134                 if (ptt->chunkId & EXTRA_HEADER_INFO_FLAG) {
135                         t->chunkId = 0;
136                         t->byteCount = 0;
137
138                         t->extraHeaderInfoAvailable = 1;
139                         t->extraParentObjectId =
140                             ptt->chunkId & (~(ALL_EXTRA_FLAGS));
141                         t->extraIsShrinkHeader =
142                             (ptt->chunkId & EXTRA_SHRINK_FLAG) ? 1 : 0;
143                         t->extraShadows =
144                             (ptt->chunkId & EXTRA_SHADOWS_FLAG) ? 1 : 0;
145                         t->extraObjectType =
146                             ptt->objectId >> EXTRA_OBJECT_TYPE_SHIFT;
147                         t->objectId &= ~EXTRA_OBJECT_TYPE_MASK;
148
149                         if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) {
150                                 t->extraEquivalentObjectId = ptt->byteCount;
151                         } else {
152                                 t->extraFileLength = ptt->byteCount;
153                         }
154                 }
155         }
156
157         yaffs_DumpPackedTags2TagsPart(ptt);
158         yaffs_DumpTags2(t);
159
160 }
161
162
163 void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 * pt)
164 {
165
166         yaffs_ECCResult eccResult = YAFFS_ECC_RESULT_NO_ERROR;
167         
168         if (pt->t.sequenceNumber != 0xFFFFFFFF) {
169                 /* Page is in use */
170 #ifndef YAFFS_IGNORE_TAGS_ECC
171                 {
172                         yaffs_ECCOther ecc;
173                         int result;
174                         yaffs_ECCCalculateOther((unsigned char *)&pt->t,
175                                                 sizeof
176                                                 (yaffs_PackedTags2TagsPart),
177                                                 &ecc);
178                         result =
179                             yaffs_ECCCorrectOther((unsigned char *)&pt->t,
180                                                   sizeof
181                                                   (yaffs_PackedTags2TagsPart),
182                                                   &pt->ecc, &ecc);
183                         switch(result){
184                                 case 0:
185                                         eccResult = YAFFS_ECC_RESULT_NO_ERROR;
186                                         break;
187                                 case 1:
188                                         eccResult = YAFFS_ECC_RESULT_FIXED;
189                                         break;
190                                 case -1:
191                                         eccResult = YAFFS_ECC_RESULT_UNFIXED;
192                                         break;
193                                 default:
194                                         eccResult = YAFFS_ECC_RESULT_UNKNOWN;
195                         }
196                 }
197 #endif
198         }
199
200         yaffs_UnpackTags2TagsPart(t,&pt->t);
201         
202         t->eccResult = eccResult;
203
204         yaffs_DumpPackedTags2(pt);
205         yaffs_DumpTags2(t);
206
207 }
208