upgrade to linux 2.6.10-1.12_FC2
[linux-2.6.git] / drivers / mtd / nftlmount.c
1 /* 
2  * NFTL mount code with extensive checks
3  *
4  * Author: Fabrice Bellard (fabrice.bellard@netgem.com) 
5  * Copyright (C) 2000 Netgem S.A.
6  *
7  * $Id: nftlmount.c,v 1.39 2004/11/05 22:51:41 kalev Exp $
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 as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23
24 #include <linux/kernel.h>
25 #include <asm/errno.h>
26 #include <linux/delay.h>
27 #include <linux/slab.h>
28 #include <linux/mtd/mtd.h>
29 #include <linux/mtd/nand.h>
30 #include <linux/mtd/nftl.h>
31
32 #define SECTORSIZE 512
33
34 char nftlmountrev[]="$Revision: 1.39 $";
35
36 /* find_boot_record: Find the NFTL Media Header and its Spare copy which contains the
37  *      various device information of the NFTL partition and Bad Unit Table. Update
38  *      the ReplUnitTable[] table accroding to the Bad Unit Table. ReplUnitTable[]
39  *      is used for management of Erase Unit in other routines in nftl.c and nftlmount.c
40  */
41 static int find_boot_record(struct NFTLrecord *nftl)
42 {
43         struct nftl_uci1 h1;
44         unsigned int block, boot_record_count = 0;
45         size_t retlen;
46         u8 buf[SECTORSIZE];
47         struct NFTLMediaHeader *mh = &nftl->MediaHdr;
48         unsigned int i;
49
50         /* Assume logical EraseSize == physical erasesize for starting the scan. 
51            We'll sort it out later if we find a MediaHeader which says otherwise */
52         /* Actually, we won't.  The new DiskOnChip driver has already scanned
53            the MediaHeader and adjusted the virtual erasesize it presents in
54            the mtd device accordingly.  We could even get rid of
55            nftl->EraseSize if there were any point in doing so. */
56         nftl->EraseSize = nftl->mbd.mtd->erasesize;
57         nftl->nb_blocks = nftl->mbd.mtd->size / nftl->EraseSize;
58
59         nftl->MediaUnit = BLOCK_NIL;
60         nftl->SpareMediaUnit = BLOCK_NIL;
61
62         /* search for a valid boot record */
63         for (block = 0; block < nftl->nb_blocks; block++) {
64                 int ret;
65
66                 /* Check for ANAND header first. Then can whinge if it's found but later
67                    checks fail */
68                 ret = MTD_READ(nftl->mbd.mtd, block * nftl->EraseSize, SECTORSIZE, &retlen, buf);
69                 /* We ignore ret in case the ECC of the MediaHeader is invalid
70                    (which is apparently acceptable) */
71                 if (retlen != SECTORSIZE) {
72                         static int warncount = 5;
73
74                         if (warncount) {
75                                 printk(KERN_WARNING "Block read at 0x%x of mtd%d failed: %d\n",
76                                        block * nftl->EraseSize, nftl->mbd.mtd->index, ret);
77                                 if (!--warncount)
78                                         printk(KERN_WARNING "Further failures for this block will not be printed\n");
79                         }
80                         continue;
81                 }
82
83                 if (retlen < 6 || memcmp(buf, "ANAND", 6)) {
84                         /* ANAND\0 not found. Continue */
85 #if 0
86                         printk(KERN_DEBUG "ANAND header not found at 0x%x in mtd%d\n", 
87                                block * nftl->EraseSize, nftl->mbd.mtd->index);
88 #endif                  
89                         continue;
90                 }
91
92                 /* To be safer with BIOS, also use erase mark as discriminant */
93                 if ((ret = MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8,
94                                 8, &retlen, (char *)&h1) < 0)) {
95                         printk(KERN_WARNING "ANAND header found at 0x%x in mtd%d, but OOB data read failed (err %d)\n",
96                                block * nftl->EraseSize, nftl->mbd.mtd->index, ret);
97                         continue;
98                 }
99
100 #if 0 /* Some people seem to have devices without ECC or erase marks
101          on the Media Header blocks. There are enough other sanity
102          checks in here that we can probably do without it.
103       */
104                 if (le16_to_cpu(h1.EraseMark | h1.EraseMark1) != ERASE_MARK) {
105                         printk(KERN_NOTICE "ANAND header found at 0x%x in mtd%d, but erase mark not present (0x%04x,0x%04x instead)\n",
106                                block * nftl->EraseSize, nftl->mbd.mtd->index, 
107                                le16_to_cpu(h1.EraseMark), le16_to_cpu(h1.EraseMark1));
108                         continue;
109                 }
110
111                 /* Finally reread to check ECC */
112                 if ((ret = MTD_READECC(nftl->mbd.mtd, block * nftl->EraseSize, SECTORSIZE,
113                                 &retlen, buf, (char *)&oob, NULL) < 0)) {
114                         printk(KERN_NOTICE "ANAND header found at 0x%x in mtd%d, but ECC read failed (err %d)\n",
115                                block * nftl->EraseSize, nftl->mbd.mtd->index, ret);
116                         continue;
117                 }
118
119                 /* Paranoia. Check the ANAND header is still there after the ECC read */
120                 if (memcmp(buf, "ANAND", 6)) {
121                         printk(KERN_NOTICE "ANAND header found at 0x%x in mtd%d, but went away on reread!\n",
122                                block * nftl->EraseSize, nftl->mbd.mtd->index);
123                         printk(KERN_NOTICE "New data are: %02x %02x %02x %02x %02x %02x\n",
124                                buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
125                         continue;
126                 }
127 #endif
128                 /* OK, we like it. */
129
130                 if (boot_record_count) {
131                         /* We've already processed one. So we just check if
132                            this one is the same as the first one we found */
133                         if (memcmp(mh, buf, sizeof(struct NFTLMediaHeader))) {
134                                 printk(KERN_NOTICE "NFTL Media Headers at 0x%x and 0x%x disagree.\n",
135                                        nftl->MediaUnit * nftl->EraseSize, block * nftl->EraseSize);
136                                 /* if (debug) Print both side by side */
137                                 if (boot_record_count < 2) {
138                                         /* We haven't yet seen two real ones */
139                                         return -1;
140                                 }
141                                 continue;
142                         }
143                         if (boot_record_count == 1)
144                                 nftl->SpareMediaUnit = block;
145
146                         /* Mark this boot record (NFTL MediaHeader) block as reserved */
147                         nftl->ReplUnitTable[block] = BLOCK_RESERVED;
148
149
150                         boot_record_count++;
151                         continue;
152                 }
153
154                 /* This is the first we've seen. Copy the media header structure into place */
155                 memcpy(mh, buf, sizeof(struct NFTLMediaHeader));
156
157                 /* Do some sanity checks on it */
158 #if 0
159 The new DiskOnChip driver scans the MediaHeader itself, and presents a virtual
160 erasesize based on UnitSizeFactor.  So the erasesize we read from the mtd
161 device is already correct.
162                 if (mh->UnitSizeFactor == 0) {
163                         printk(KERN_NOTICE "NFTL: UnitSizeFactor 0x00 detected. This violates the spec but we think we know what it means...\n");
164                 } else if (mh->UnitSizeFactor < 0xfc) {
165                         printk(KERN_NOTICE "Sorry, we don't support UnitSizeFactor 0x%02x\n",
166                                mh->UnitSizeFactor);
167                         return -1;
168                 } else if (mh->UnitSizeFactor != 0xff) {
169                         printk(KERN_NOTICE "WARNING: Support for NFTL with UnitSizeFactor 0x%02x is experimental\n",
170                                mh->UnitSizeFactor);
171                         nftl->EraseSize = nftl->mbd.mtd->erasesize << (0xff - mh->UnitSizeFactor);
172                         nftl->nb_blocks = nftl->mbd.mtd->size / nftl->EraseSize;
173                 }
174 #endif
175                 nftl->nb_boot_blocks = le16_to_cpu(mh->FirstPhysicalEUN);
176                 if ((nftl->nb_boot_blocks + 2) >= nftl->nb_blocks) {
177                         printk(KERN_NOTICE "NFTL Media Header sanity check failed:\n");
178                         printk(KERN_NOTICE "nb_boot_blocks (%d) + 2 > nb_blocks (%d)\n", 
179                                nftl->nb_boot_blocks, nftl->nb_blocks);
180                         return -1;
181                 }
182
183                 nftl->numvunits = le32_to_cpu(mh->FormattedSize) / nftl->EraseSize;
184                 if (nftl->numvunits > (nftl->nb_blocks - nftl->nb_boot_blocks - 2)) {
185                         printk(KERN_NOTICE "NFTL Media Header sanity check failed:\n");
186                         printk(KERN_NOTICE "numvunits (%d) > nb_blocks (%d) - nb_boot_blocks(%d) - 2\n",
187                                nftl->numvunits, nftl->nb_blocks, nftl->nb_boot_blocks);
188                         return -1;
189                 }
190                 
191                 nftl->mbd.size  = nftl->numvunits * (nftl->EraseSize / SECTORSIZE);
192
193                 /* If we're not using the last sectors in the device for some reason,
194                    reduce nb_blocks accordingly so we forget they're there */
195                 nftl->nb_blocks = le16_to_cpu(mh->NumEraseUnits) + le16_to_cpu(mh->FirstPhysicalEUN);
196
197                 /* XXX: will be suppressed */
198                 nftl->lastEUN = nftl->nb_blocks - 1;
199
200                 /* memory alloc */
201                 nftl->EUNtable = kmalloc(nftl->nb_blocks * sizeof(u16), GFP_KERNEL);
202                 if (!nftl->EUNtable) {
203                         printk(KERN_NOTICE "NFTL: allocation of EUNtable failed\n");
204                         return -ENOMEM;
205                 }
206
207                 nftl->ReplUnitTable = kmalloc(nftl->nb_blocks * sizeof(u16), GFP_KERNEL);
208                 if (!nftl->ReplUnitTable) {
209                         kfree(nftl->EUNtable);
210                         printk(KERN_NOTICE "NFTL: allocation of ReplUnitTable failed\n");
211                         return -ENOMEM;
212                 }
213                 
214                 /* mark the bios blocks (blocks before NFTL MediaHeader) as reserved */
215                 for (i = 0; i < nftl->nb_boot_blocks; i++)
216                         nftl->ReplUnitTable[i] = BLOCK_RESERVED;
217                 /* mark all remaining blocks as potentially containing data */
218                 for (; i < nftl->nb_blocks; i++) { 
219                         nftl->ReplUnitTable[i] = BLOCK_NOTEXPLORED;
220                 }
221
222                 /* Mark this boot record (NFTL MediaHeader) block as reserved */
223                 nftl->ReplUnitTable[block] = BLOCK_RESERVED;
224
225                 /* read the Bad Erase Unit Table and modify ReplUnitTable[] accordingly */
226                 for (i = 0; i < nftl->nb_blocks; i++) {
227 #if 0
228 The new DiskOnChip driver already scanned the bad block table.  Just query it.
229                         if ((i & (SECTORSIZE - 1)) == 0) {
230                                 /* read one sector for every SECTORSIZE of blocks */
231                                 if ((ret = MTD_READECC(nftl->mbd.mtd, block * nftl->EraseSize +
232                                                        i + SECTORSIZE, SECTORSIZE, &retlen, buf,
233                                                        (char *)&oob, NULL)) < 0) {
234                                         printk(KERN_NOTICE "Read of bad sector table failed (err %d)\n",
235                                                ret);
236                                         kfree(nftl->ReplUnitTable);
237                                         kfree(nftl->EUNtable);
238                                         return -1;
239                                 }
240                         }
241                         /* mark the Bad Erase Unit as RESERVED in ReplUnitTable */
242                         if (buf[i & (SECTORSIZE - 1)] != 0xff)
243                                 nftl->ReplUnitTable[i] = BLOCK_RESERVED;
244 #endif
245                         if (nftl->mbd.mtd->block_isbad(nftl->mbd.mtd, i * nftl->EraseSize))
246                                 nftl->ReplUnitTable[i] = BLOCK_RESERVED;
247                 }
248                 
249                 nftl->MediaUnit = block;
250                 boot_record_count++;
251                 
252         } /* foreach (block) */
253                 
254         return boot_record_count?0:-1;
255 }
256
257 static int memcmpb(void *a, int c, int n)
258 {
259         int i;
260         for (i = 0; i < n; i++) {
261                 if (c != ((unsigned char *)a)[i])
262                         return 1;
263         }
264         return 0;
265 }
266
267 /* check_free_sector: check if a free sector is actually FREE, i.e. All 0xff in data and oob area */
268 static int check_free_sectors(struct NFTLrecord *nftl, unsigned int address, int len, 
269                               int check_oob)
270 {
271         int i;
272         size_t retlen;
273         u8 buf[SECTORSIZE + nftl->mbd.mtd->oobsize];
274
275         for (i = 0; i < len; i += SECTORSIZE) {
276                 if (MTD_READECC(nftl->mbd.mtd, address, SECTORSIZE, &retlen, buf, &buf[SECTORSIZE], &nftl->oobinfo) < 0)
277                         return -1;
278                 if (memcmpb(buf, 0xff, SECTORSIZE) != 0)
279                         return -1;
280
281                 if (check_oob) {
282                         if (memcmpb(buf + SECTORSIZE, 0xff, nftl->mbd.mtd->oobsize) != 0)
283                                 return -1;
284                 }
285                 address += SECTORSIZE;
286         }
287
288         return 0;
289 }
290
291 /* NFTL_format: format a Erase Unit by erasing ALL Erase Zones in the Erase Unit and
292  *              Update NFTL metadata. Each erase operation is checked with check_free_sectors
293  *
294  * Return: 0 when succeed, -1 on error.
295  *
296  *  ToDo: 1. Is it neceressary to check_free_sector after erasing ?? 
297  */
298 int NFTL_formatblock(struct NFTLrecord *nftl, int block)
299 {
300         size_t retlen;
301         unsigned int nb_erases, erase_mark;
302         struct nftl_uci1 uci;
303         struct erase_info *instr = &nftl->instr;
304
305         instr->mtd = nftl->mbd.mtd;
306
307         /* Read the Unit Control Information #1 for Wear-Leveling */
308         if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8,
309                         8, &retlen, (char *)&uci) < 0)
310                 goto default_uci1;
311
312         erase_mark = le16_to_cpu ((uci.EraseMark | uci.EraseMark1));
313         if (erase_mark != ERASE_MARK) {
314         default_uci1:
315                 uci.EraseMark = cpu_to_le16(ERASE_MARK);
316                 uci.EraseMark1 = cpu_to_le16(ERASE_MARK);
317                 uci.WearInfo = cpu_to_le32(0);
318         }
319
320         memset(instr, 0, sizeof(struct erase_info));
321
322         /* XXX: use async erase interface, XXX: test return code */
323         instr->addr = block * nftl->EraseSize;
324         instr->len = nftl->EraseSize;
325         MTD_ERASE(nftl->mbd.mtd, instr);
326
327         if (instr->state == MTD_ERASE_FAILED) {
328                 printk("Error while formatting block %d\n", block);
329                 goto fail;
330         }
331
332                 /* increase and write Wear-Leveling info */
333                 nb_erases = le32_to_cpu(uci.WearInfo);
334                 nb_erases++;
335
336                 /* wrap (almost impossible with current flashs) or free block */
337                 if (nb_erases == 0)
338                         nb_erases = 1;
339
340                 /* check the "freeness" of Erase Unit before updating metadata
341                  * FixMe:  is this check really necessary ? since we have check the
342                  *         return code after the erase operation. */
343                 if (check_free_sectors(nftl, instr->addr, nftl->EraseSize, 1) != 0)
344                         goto fail;
345
346                 uci.WearInfo = le32_to_cpu(nb_erases);
347                 if (MTD_WRITEOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8,
348                                  &retlen, (char *)&uci) < 0)
349                         goto fail;
350                 return 0;
351 fail:
352         /* could not format, update the bad block table (caller is responsible
353            for setting the ReplUnitTable to BLOCK_RESERVED on failure) */
354         nftl->mbd.mtd->block_markbad(nftl->mbd.mtd, instr->addr);
355         return -1;
356 }
357
358 /* check_sectors_in_chain: Check that each sector of a Virtual Unit Chain is correct.
359  *      Mark as 'IGNORE' each incorrect sector. This check is only done if the chain
360  *      was being folded when NFTL was interrupted.
361  *
362  *      The check_free_sectors in this function is neceressary. There is a possible
363  *      situation that after writing the Data area, the Block Control Information is
364  *      not updated according (due to power failure or something) which leaves the block
365  *      in an umconsistent state. So we have to check if a block is really FREE in this
366  *      case. */
367 static void check_sectors_in_chain(struct NFTLrecord *nftl, unsigned int first_block)
368 {
369         unsigned int block, i, status;
370         struct nftl_bci bci;
371         int sectors_per_block;
372         size_t retlen;
373
374         sectors_per_block = nftl->EraseSize / SECTORSIZE;
375         block = first_block;
376         for (;;) {
377                 for (i = 0; i < sectors_per_block; i++) {
378                         if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + i * SECTORSIZE,
379                                         8, &retlen, (char *)&bci) < 0)
380                                 status = SECTOR_IGNORE;
381                         else
382                                 status = bci.Status | bci.Status1;
383
384                         switch(status) {
385                         case SECTOR_FREE:
386                                 /* verify that the sector is really free. If not, mark
387                                    as ignore */
388                                 if (memcmpb(&bci, 0xff, 8) != 0 ||
389                                     check_free_sectors(nftl, block * nftl->EraseSize + i * SECTORSIZE, 
390                                                        SECTORSIZE, 0) != 0) {
391                                         printk("Incorrect free sector %d in block %d: "
392                                                "marking it as ignored\n",
393                                                i, block);
394
395                                         /* sector not free actually : mark it as SECTOR_IGNORE  */
396                                         bci.Status = SECTOR_IGNORE;
397                                         bci.Status1 = SECTOR_IGNORE;
398                                         MTD_WRITEOOB(nftl->mbd.mtd,
399                                                      block * nftl->EraseSize + i * SECTORSIZE,
400                                                      8, &retlen, (char *)&bci);
401                                 }
402                                 break;
403                         default:
404                                 break;
405                         }
406                 }
407
408                 /* proceed to next Erase Unit on the chain */
409                 block = nftl->ReplUnitTable[block];
410                 if (!(block == BLOCK_NIL || block < nftl->nb_blocks))
411                         printk("incorrect ReplUnitTable[] : %d\n", block);
412                 if (block == BLOCK_NIL || block >= nftl->nb_blocks)
413                         break;
414         }
415 }
416
417 /* calc_chain_lenght: Walk through a Virtual Unit Chain and estimate chain length */
418 static int calc_chain_length(struct NFTLrecord *nftl, unsigned int first_block)
419 {
420         unsigned int length = 0, block = first_block;
421
422         for (;;) {
423                 length++;
424                 /* avoid infinite loops, although this is guaranted not to
425                    happen because of the previous checks */
426                 if (length >= nftl->nb_blocks) {
427                         printk("nftl: length too long %d !\n", length);
428                         break;
429                 }
430
431                 block = nftl->ReplUnitTable[block];
432                 if (!(block == BLOCK_NIL || block < nftl->nb_blocks))
433                         printk("incorrect ReplUnitTable[] : %d\n", block);
434                 if (block == BLOCK_NIL || block >= nftl->nb_blocks)
435                         break;
436         }
437         return length;
438 }
439
440 /* format_chain: Format an invalid Virtual Unit chain. It frees all the Erase Units in a
441  *      Virtual Unit Chain, i.e. all the units are disconnected.
442  *
443  *      It is not stricly correct to begin from the first block of the chain because
444  *      if we stop the code, we may see again a valid chain if there was a first_block
445  *      flag in a block inside it. But is it really a problem ?
446  *
447  * FixMe: Figure out what the last statesment means. What if power failure when we are
448  *      in the for (;;) loop formatting blocks ??
449  */
450 static void format_chain(struct NFTLrecord *nftl, unsigned int first_block)
451 {
452         unsigned int block = first_block, block1;
453
454         printk("Formatting chain at block %d\n", first_block);
455
456         for (;;) {
457                 block1 = nftl->ReplUnitTable[block];
458
459                 printk("Formatting block %d\n", block);
460                 if (NFTL_formatblock(nftl, block) < 0) {
461                         /* cannot format !!!! Mark it as Bad Unit */
462                         nftl->ReplUnitTable[block] = BLOCK_RESERVED;
463                 } else {
464                         nftl->ReplUnitTable[block] = BLOCK_FREE;
465                 }
466
467                 /* goto next block on the chain */
468                 block = block1;
469
470                 if (!(block == BLOCK_NIL || block < nftl->nb_blocks))
471                         printk("incorrect ReplUnitTable[] : %d\n", block);
472                 if (block == BLOCK_NIL || block >= nftl->nb_blocks)
473                         break;
474         }
475 }
476
477 /* check_and_mark_free_block: Verify that a block is free in the NFTL sense (valid erase mark) or
478  *      totally free (only 0xff).
479  *
480  * Definition: Free Erase Unit -- A properly erased/formatted Free Erase Unit should have meet the
481  *      following critia:
482  *      1. */
483 static int check_and_mark_free_block(struct NFTLrecord *nftl, int block)
484 {
485         struct nftl_uci1 h1;
486         unsigned int erase_mark;
487         size_t retlen;
488
489         /* check erase mark. */
490         if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8, 
491                         &retlen, (char *)&h1) < 0)
492                 return -1;
493
494         erase_mark = le16_to_cpu ((h1.EraseMark | h1.EraseMark1));
495         if (erase_mark != ERASE_MARK) {
496                 /* if no erase mark, the block must be totally free. This is
497                    possible in two cases : empty filsystem or interrupted erase (very unlikely) */
498                 if (check_free_sectors (nftl, block * nftl->EraseSize, nftl->EraseSize, 1) != 0)
499                         return -1;
500
501                 /* free block : write erase mark */
502                 h1.EraseMark = cpu_to_le16(ERASE_MARK);
503                 h1.EraseMark1 = cpu_to_le16(ERASE_MARK);
504                 h1.WearInfo = cpu_to_le32(0);
505                 if (MTD_WRITEOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8, 
506                                  &retlen, (char *)&h1) < 0)
507                         return -1;
508         } else {
509 #if 0
510                 /* if erase mark present, need to skip it when doing check */
511                 for (i = 0; i < nftl->EraseSize; i += SECTORSIZE) {
512                         /* check free sector */
513                         if (check_free_sectors (nftl, block * nftl->EraseSize + i,
514                                                 SECTORSIZE, 0) != 0)
515                                 return -1;
516
517                         if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + i,
518                                         16, &retlen, buf) < 0)
519                                 return -1;
520                         if (i == SECTORSIZE) {
521                                 /* skip erase mark */
522                                 if (memcmpb(buf, 0xff, 8))
523                                         return -1;
524                         } else {
525                                 if (memcmpb(buf, 0xff, 16))
526                                         return -1;
527                         }
528                 }
529 #endif
530         }
531
532         return 0;
533 }
534
535 /* get_fold_mark: Read fold mark from Unit Control Information #2, we use FOLD_MARK_IN_PROGRESS
536  *      to indicate that we are in the progression of a Virtual Unit Chain folding. If the UCI #2
537  *      is FOLD_MARK_IN_PROGRESS when mounting the NFTL, the (previous) folding process is interrupted
538  *      for some reason. A clean up/check of the VUC is neceressary in this case.
539  *
540  * WARNING: return 0 if read error
541  */
542 static int get_fold_mark(struct NFTLrecord *nftl, unsigned int block)
543 {
544         struct nftl_uci2 uci;
545         size_t retlen;
546
547         if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + 2 * SECTORSIZE + 8,
548                         8, &retlen, (char *)&uci) < 0)
549                 return 0;
550
551         return le16_to_cpu((uci.FoldMark | uci.FoldMark1));
552 }
553
554 int NFTL_mount(struct NFTLrecord *s)
555 {
556         int i;
557         unsigned int first_logical_block, logical_block, rep_block, nb_erases, erase_mark;
558         unsigned int block, first_block, is_first_block;
559         int chain_length, do_format_chain;
560         struct nftl_uci0 h0;
561         struct nftl_uci1 h1;
562         size_t retlen;
563
564         /* search for NFTL MediaHeader and Spare NFTL Media Header */
565         if (find_boot_record(s) < 0) {
566                 printk("Could not find valid boot record\n");
567                 return -1;
568         }
569
570         /* init the logical to physical table */
571         for (i = 0; i < s->nb_blocks; i++) {
572                 s->EUNtable[i] = BLOCK_NIL;
573         }
574
575         /* first pass : explore each block chain */
576         first_logical_block = 0;
577         for (first_block = 0; first_block < s->nb_blocks; first_block++) {
578                 /* if the block was not already explored, we can look at it */
579                 if (s->ReplUnitTable[first_block] == BLOCK_NOTEXPLORED) {
580                         block = first_block;
581                         chain_length = 0;
582                         do_format_chain = 0;
583
584                         for (;;) {
585                                 /* read the block header. If error, we format the chain */
586                                 if (MTD_READOOB(s->mbd.mtd, block * s->EraseSize + 8, 8, 
587                                                 &retlen, (char *)&h0) < 0 ||
588                                     MTD_READOOB(s->mbd.mtd, block * s->EraseSize + SECTORSIZE + 8, 8, 
589                                                 &retlen, (char *)&h1) < 0) {
590                                         s->ReplUnitTable[block] = BLOCK_NIL;
591                                         do_format_chain = 1;
592                                         break;
593                                 }
594
595                                 logical_block = le16_to_cpu ((h0.VirtUnitNum | h0.SpareVirtUnitNum));
596                                 rep_block = le16_to_cpu ((h0.ReplUnitNum | h0.SpareReplUnitNum));
597                                 nb_erases = le32_to_cpu (h1.WearInfo);
598                                 erase_mark = le16_to_cpu ((h1.EraseMark | h1.EraseMark1));
599
600                                 is_first_block = !(logical_block >> 15);
601                                 logical_block = logical_block & 0x7fff;
602
603                                 /* invalid/free block test */
604                                 if (erase_mark != ERASE_MARK || logical_block >= s->nb_blocks) {
605                                         if (chain_length == 0) {
606                                                 /* if not currently in a chain, we can handle it safely */
607                                                 if (check_and_mark_free_block(s, block) < 0) {
608                                                         /* not really free: format it */
609                                                         printk("Formatting block %d\n", block);
610                                                         if (NFTL_formatblock(s, block) < 0) {
611                                                                 /* could not format: reserve the block */
612                                                                 s->ReplUnitTable[block] = BLOCK_RESERVED;
613                                                         } else {
614                                                                 s->ReplUnitTable[block] = BLOCK_FREE;
615                                                         }
616                                                 } else {
617                                                         /* free block: mark it */
618                                                         s->ReplUnitTable[block] = BLOCK_FREE;
619                                                 }
620                                                 /* directly examine the next block. */
621                                                 goto examine_ReplUnitTable;
622                                         } else {
623                                                 /* the block was in a chain : this is bad. We
624                                                    must format all the chain */
625                                                 printk("Block %d: free but referenced in chain %d\n",
626                                                        block, first_block);
627                                                 s->ReplUnitTable[block] = BLOCK_NIL;
628                                                 do_format_chain = 1;
629                                                 break;
630                                         }
631                                 }
632
633                                 /* we accept only first blocks here */
634                                 if (chain_length == 0) {
635                                         /* this block is not the first block in chain :
636                                            ignore it, it will be included in a chain
637                                            later, or marked as not explored */
638                                         if (!is_first_block)
639                                                 goto examine_ReplUnitTable;
640                                         first_logical_block = logical_block;
641                                 } else {
642                                         if (logical_block != first_logical_block) {
643                                                 printk("Block %d: incorrect logical block: %d expected: %d\n", 
644                                                        block, logical_block, first_logical_block);
645                                                 /* the chain is incorrect : we must format it,
646                                                    but we need to read it completly */
647                                                 do_format_chain = 1;
648                                         }
649                                         if (is_first_block) {
650                                                 /* we accept that a block is marked as first
651                                                    block while being last block in a chain
652                                                    only if the chain is being folded */
653                                                 if (get_fold_mark(s, block) != FOLD_MARK_IN_PROGRESS ||
654                                                     rep_block != 0xffff) {
655                                                         printk("Block %d: incorrectly marked as first block in chain\n",
656                                                                block);
657                                                         /* the chain is incorrect : we must format it,
658                                                            but we need to read it completly */
659                                                         do_format_chain = 1;
660                                                 } else {
661                                                         printk("Block %d: folding in progress - ignoring first block flag\n",
662                                                                block);
663                                                 }
664                                         }
665                                 }
666                                 chain_length++;
667                                 if (rep_block == 0xffff) {
668                                         /* no more blocks after */
669                                         s->ReplUnitTable[block] = BLOCK_NIL;
670                                         break;
671                                 } else if (rep_block >= s->nb_blocks) {
672                                         printk("Block %d: referencing invalid block %d\n", 
673                                                block, rep_block);
674                                         do_format_chain = 1;
675                                         s->ReplUnitTable[block] = BLOCK_NIL;
676                                         break;
677                                 } else if (s->ReplUnitTable[rep_block] != BLOCK_NOTEXPLORED) {
678                                         /* same problem as previous 'is_first_block' test:
679                                            we accept that the last block of a chain has
680                                            the first_block flag set if folding is in
681                                            progress. We handle here the case where the
682                                            last block appeared first */
683                                         if (s->ReplUnitTable[rep_block] == BLOCK_NIL &&
684                                             s->EUNtable[first_logical_block] == rep_block &&
685                                             get_fold_mark(s, first_block) == FOLD_MARK_IN_PROGRESS) {
686                                                 /* EUNtable[] will be set after */
687                                                 printk("Block %d: folding in progress - ignoring first block flag\n",
688                                                        rep_block);
689                                                 s->ReplUnitTable[block] = rep_block;
690                                                 s->EUNtable[first_logical_block] = BLOCK_NIL;
691                                         } else {
692                                                 printk("Block %d: referencing block %d already in another chain\n", 
693                                                        block, rep_block);
694                                                 /* XXX: should handle correctly fold in progress chains */
695                                                 do_format_chain = 1;
696                                                 s->ReplUnitTable[block] = BLOCK_NIL;
697                                         }
698                                         break;
699                                 } else {
700                                         /* this is OK */
701                                         s->ReplUnitTable[block] = rep_block;
702                                         block = rep_block;
703                                 }
704                         }
705
706                         /* the chain was completely explored. Now we can decide
707                            what to do with it */
708                         if (do_format_chain) {
709                                 /* invalid chain : format it */
710                                 format_chain(s, first_block);
711                         } else {
712                                 unsigned int first_block1, chain_to_format, chain_length1;
713                                 int fold_mark;
714                                 
715                                 /* valid chain : get foldmark */
716                                 fold_mark = get_fold_mark(s, first_block);
717                                 if (fold_mark == 0) {
718                                         /* cannot get foldmark : format the chain */
719                                         printk("Could read foldmark at block %d\n", first_block);
720                                         format_chain(s, first_block);
721                                 } else {
722                                         if (fold_mark == FOLD_MARK_IN_PROGRESS)
723                                                 check_sectors_in_chain(s, first_block);
724
725                                         /* now handle the case where we find two chains at the
726                                            same virtual address : we select the longer one,
727                                            because the shorter one is the one which was being
728                                            folded if the folding was not done in place */
729                                         first_block1 = s->EUNtable[first_logical_block];
730                                         if (first_block1 != BLOCK_NIL) {
731                                                 /* XXX: what to do if same length ? */
732                                                 chain_length1 = calc_chain_length(s, first_block1);
733                                                 printk("Two chains at blocks %d (len=%d) and %d (len=%d)\n", 
734                                                        first_block1, chain_length1, first_block, chain_length);
735                                                 
736                                                 if (chain_length >= chain_length1) {
737                                                         chain_to_format = first_block1;
738                                                         s->EUNtable[first_logical_block] = first_block;
739                                                 } else {
740                                                         chain_to_format = first_block;
741                                                 }
742                                                 format_chain(s, chain_to_format);
743                                         } else {
744                                                 s->EUNtable[first_logical_block] = first_block;
745                                         }
746                                 }
747                         }
748                 }
749         examine_ReplUnitTable:;
750         }
751
752         /* second pass to format unreferenced blocks  and init free block count */
753         s->numfreeEUNs = 0;
754         s->LastFreeEUN = le16_to_cpu(s->MediaHdr.FirstPhysicalEUN);
755
756         for (block = 0; block < s->nb_blocks; block++) {
757                 if (s->ReplUnitTable[block] == BLOCK_NOTEXPLORED) {
758                         printk("Unreferenced block %d, formatting it\n", block);
759                         if (NFTL_formatblock(s, block) < 0)
760                                 s->ReplUnitTable[block] = BLOCK_RESERVED;
761                         else
762                                 s->ReplUnitTable[block] = BLOCK_FREE;
763                 }
764                 if (s->ReplUnitTable[block] == BLOCK_FREE) {
765                         s->numfreeEUNs++;
766                         s->LastFreeEUN = block;
767                 }
768         }
769
770         return 0;
771 }