summaryrefslogtreecommitdiffstats
path: root/linux-2.4.x/drivers/mtd/nftlmount.c
diff options
context:
space:
mode:
Diffstat (limited to 'linux-2.4.x/drivers/mtd/nftlmount.c')
-rw-r--r--linux-2.4.x/drivers/mtd/nftlmount.c263
1 files changed, 144 insertions, 119 deletions
diff --git a/linux-2.4.x/drivers/mtd/nftlmount.c b/linux-2.4.x/drivers/mtd/nftlmount.c
index 56b42a5..3b104eb 100644
--- a/linux-2.4.x/drivers/mtd/nftlmount.c
+++ b/linux-2.4.x/drivers/mtd/nftlmount.c
@@ -1,10 +1,10 @@
-/*
+/*
* NFTL mount code with extensive checks
*
- * Author: Fabrice Bellard (fabrice.bellard@netgem.com)
+ * Author: Fabrice Bellard (fabrice.bellard@netgem.com)
* Copyright (C) 2000 Netgem S.A.
*
- * $Id: nftlmount.c,v 1.25 2001/11/30 16:46:27 dwmw2 Exp $
+ * $Id: nftlmount.c,v 1.41 2005/11/07 11:14:21 gleixner Exp $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -21,25 +21,17 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#define __NO_VERSION__
#include <linux/kernel.h>
-#include <linux/module.h>
#include <asm/errno.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <linux/miscdevice.h>
-#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/slab.h>
-#include <linux/sched.h>
-#include <linux/init.h>
#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
#include <linux/mtd/nftl.h>
-#include <linux/mtd/compatmac.h>
#define SECTORSIZE 512
-char nftlmountrev[]="$Revision: 1.25 $";
+char nftlmountrev[]="$Revision: 1.41 $";
/* find_boot_record: Find the NFTL Media Header and its Spare copy which contains the
* various device information of the NFTL partition and Bad Unit Table. Update
@@ -49,13 +41,21 @@ char nftlmountrev[]="$Revision: 1.25 $";
static int find_boot_record(struct NFTLrecord *nftl)
{
struct nftl_uci1 h1;
- struct nftl_oob oob;
unsigned int block, boot_record_count = 0;
- int retlen;
+ size_t retlen;
u8 buf[SECTORSIZE];
struct NFTLMediaHeader *mh = &nftl->MediaHdr;
unsigned int i;
+ /* Assume logical EraseSize == physical erasesize for starting the scan.
+ We'll sort it out later if we find a MediaHeader which says otherwise */
+ /* Actually, we won't. The new DiskOnChip driver has already scanned
+ the MediaHeader and adjusted the virtual erasesize it presents in
+ the mtd device accordingly. We could even get rid of
+ nftl->EraseSize if there were any point in doing so. */
+ nftl->EraseSize = nftl->mbd.mtd->erasesize;
+ nftl->nb_blocks = nftl->mbd.mtd->size / nftl->EraseSize;
+
nftl->MediaUnit = BLOCK_NIL;
nftl->SpareMediaUnit = BLOCK_NIL;
@@ -65,12 +65,15 @@ static int find_boot_record(struct NFTLrecord *nftl)
/* Check for ANAND header first. Then can whinge if it's found but later
checks fail */
- if ((ret = MTD_READ(nftl->mtd, block * nftl->EraseSize, SECTORSIZE, &retlen, buf))) {
+ ret = MTD_READ(nftl->mbd.mtd, block * nftl->EraseSize, SECTORSIZE, &retlen, buf);
+ /* We ignore ret in case the ECC of the MediaHeader is invalid
+ (which is apparently acceptable) */
+ if (retlen != SECTORSIZE) {
static int warncount = 5;
if (warncount) {
printk(KERN_WARNING "Block read at 0x%x of mtd%d failed: %d\n",
- block * nftl->EraseSize, nftl->mtd->index, ret);
+ block * nftl->EraseSize, nftl->mbd.mtd->index, ret);
if (!--warncount)
printk(KERN_WARNING "Further failures for this block will not be printed\n");
}
@@ -80,17 +83,17 @@ static int find_boot_record(struct NFTLrecord *nftl)
if (retlen < 6 || memcmp(buf, "ANAND", 6)) {
/* ANAND\0 not found. Continue */
#if 0
- printk(KERN_DEBUG "ANAND header not found at 0x%x in mtd%d\n",
- block * nftl->EraseSize, nftl->mtd->index);
-#endif
+ printk(KERN_DEBUG "ANAND header not found at 0x%x in mtd%d\n",
+ block * nftl->EraseSize, nftl->mbd.mtd->index);
+#endif
continue;
}
/* To be safer with BIOS, also use erase mark as discriminant */
- if ((ret = MTD_READOOB(nftl->mtd, block * nftl->EraseSize + SECTORSIZE + 8,
+ if ((ret = MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8,
8, &retlen, (char *)&h1) < 0)) {
printk(KERN_WARNING "ANAND header found at 0x%x in mtd%d, but OOB data read failed (err %d)\n",
- block * nftl->EraseSize, nftl->mtd->index, ret);
+ block * nftl->EraseSize, nftl->mbd.mtd->index, ret);
continue;
}
@@ -100,29 +103,28 @@ static int find_boot_record(struct NFTLrecord *nftl)
*/
if (le16_to_cpu(h1.EraseMark | h1.EraseMark1) != ERASE_MARK) {
printk(KERN_NOTICE "ANAND header found at 0x%x in mtd%d, but erase mark not present (0x%04x,0x%04x instead)\n",
- block * nftl->EraseSize, nftl->mtd->index,
+ block * nftl->EraseSize, nftl->mbd.mtd->index,
le16_to_cpu(h1.EraseMark), le16_to_cpu(h1.EraseMark1));
continue;
}
/* Finally reread to check ECC */
- if ((ret = MTD_READECC(nftl->mtd, block * nftl->EraseSize, SECTORSIZE,
- &retlen, buf, (char *)&oob) < 0)) {
+ if ((ret = MTD_READECC(nftl->mbd.mtd, block * nftl->EraseSize, SECTORSIZE,
+ &retlen, buf, (char *)&oob, NULL) < 0)) {
printk(KERN_NOTICE "ANAND header found at 0x%x in mtd%d, but ECC read failed (err %d)\n",
- block * nftl->EraseSize, nftl->mtd->index, ret);
+ block * nftl->EraseSize, nftl->mbd.mtd->index, ret);
continue;
}
/* Paranoia. Check the ANAND header is still there after the ECC read */
if (memcmp(buf, "ANAND", 6)) {
printk(KERN_NOTICE "ANAND header found at 0x%x in mtd%d, but went away on reread!\n",
- block * nftl->EraseSize, nftl->mtd->index);
+ block * nftl->EraseSize, nftl->mbd.mtd->index);
printk(KERN_NOTICE "New data are: %02x %02x %02x %02x %02x %02x\n",
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
continue;
}
#endif
-
/* OK, we like it. */
if (boot_record_count) {
@@ -132,11 +134,19 @@ static int find_boot_record(struct NFTLrecord *nftl)
printk(KERN_NOTICE "NFTL Media Headers at 0x%x and 0x%x disagree.\n",
nftl->MediaUnit * nftl->EraseSize, block * nftl->EraseSize);
/* if (debug) Print both side by side */
- return -1;
+ if (boot_record_count < 2) {
+ /* We haven't yet seen two real ones */
+ return -1;
+ }
+ continue;
}
if (boot_record_count == 1)
nftl->SpareMediaUnit = block;
+ /* Mark this boot record (NFTL MediaHeader) block as reserved */
+ nftl->ReplUnitTable[block] = BLOCK_RESERVED;
+
+
boot_record_count++;
continue;
}
@@ -145,16 +155,27 @@ static int find_boot_record(struct NFTLrecord *nftl)
memcpy(mh, buf, sizeof(struct NFTLMediaHeader));
/* Do some sanity checks on it */
- if (mh->UnitSizeFactor != 0xff) {
- printk(KERN_NOTICE "Sorry, we don't support UnitSizeFactor "
- "of != 1 yet.\n");
+#if 0
+The new DiskOnChip driver scans the MediaHeader itself, and presents a virtual
+erasesize based on UnitSizeFactor. So the erasesize we read from the mtd
+device is already correct.
+ if (mh->UnitSizeFactor == 0) {
+ printk(KERN_NOTICE "NFTL: UnitSizeFactor 0x00 detected. This violates the spec but we think we know what it means...\n");
+ } else if (mh->UnitSizeFactor < 0xfc) {
+ printk(KERN_NOTICE "Sorry, we don't support UnitSizeFactor 0x%02x\n",
+ mh->UnitSizeFactor);
return -1;
+ } else if (mh->UnitSizeFactor != 0xff) {
+ printk(KERN_NOTICE "WARNING: Support for NFTL with UnitSizeFactor 0x%02x is experimental\n",
+ mh->UnitSizeFactor);
+ nftl->EraseSize = nftl->mbd.mtd->erasesize << (0xff - mh->UnitSizeFactor);
+ nftl->nb_blocks = nftl->mbd.mtd->size / nftl->EraseSize;
}
-
+#endif
nftl->nb_boot_blocks = le16_to_cpu(mh->FirstPhysicalEUN);
if ((nftl->nb_boot_blocks + 2) >= nftl->nb_blocks) {
printk(KERN_NOTICE "NFTL Media Header sanity check failed:\n");
- printk(KERN_NOTICE "nb_boot_blocks (%d) + 2 > nb_blocks (%d)\n",
+ printk(KERN_NOTICE "nb_boot_blocks (%d) + 2 > nb_blocks (%d)\n",
nftl->nb_boot_blocks, nftl->nb_blocks);
return -1;
}
@@ -166,35 +187,70 @@ static int find_boot_record(struct NFTLrecord *nftl)
nftl->numvunits, nftl->nb_blocks, nftl->nb_boot_blocks);
return -1;
}
-
- nftl->nr_sects = nftl->numvunits * (nftl->EraseSize / SECTORSIZE);
-
+
+ nftl->mbd.size = nftl->numvunits * (nftl->EraseSize / SECTORSIZE);
+
/* If we're not using the last sectors in the device for some reason,
reduce nb_blocks accordingly so we forget they're there */
nftl->nb_blocks = le16_to_cpu(mh->NumEraseUnits) + le16_to_cpu(mh->FirstPhysicalEUN);
+ /* XXX: will be suppressed */
+ nftl->lastEUN = nftl->nb_blocks - 1;
+
+ /* memory alloc */
+ nftl->EUNtable = kmalloc(nftl->nb_blocks * sizeof(u16), GFP_KERNEL);
+ if (!nftl->EUNtable) {
+ printk(KERN_NOTICE "NFTL: allocation of EUNtable failed\n");
+ return -ENOMEM;
+ }
+
+ nftl->ReplUnitTable = kmalloc(nftl->nb_blocks * sizeof(u16), GFP_KERNEL);
+ if (!nftl->ReplUnitTable) {
+ kfree(nftl->EUNtable);
+ printk(KERN_NOTICE "NFTL: allocation of ReplUnitTable failed\n");
+ return -ENOMEM;
+ }
+
+ /* mark the bios blocks (blocks before NFTL MediaHeader) as reserved */
+ for (i = 0; i < nftl->nb_boot_blocks; i++)
+ nftl->ReplUnitTable[i] = BLOCK_RESERVED;
+ /* mark all remaining blocks as potentially containing data */
+ for (; i < nftl->nb_blocks; i++) {
+ nftl->ReplUnitTable[i] = BLOCK_NOTEXPLORED;
+ }
+
+ /* Mark this boot record (NFTL MediaHeader) block as reserved */
+ nftl->ReplUnitTable[block] = BLOCK_RESERVED;
+
/* read the Bad Erase Unit Table and modify ReplUnitTable[] accordingly */
for (i = 0; i < nftl->nb_blocks; i++) {
+#if 0
+The new DiskOnChip driver already scanned the bad block table. Just query it.
if ((i & (SECTORSIZE - 1)) == 0) {
/* read one sector for every SECTORSIZE of blocks */
- if ((ret = MTD_READECC(nftl->mtd, block * nftl->EraseSize +
- i + SECTORSIZE, SECTORSIZE,
- &retlen, buf, (char *)&oob)) < 0) {
+ if ((ret = MTD_READECC(nftl->mbd.mtd, block * nftl->EraseSize +
+ i + SECTORSIZE, SECTORSIZE, &retlen, buf,
+ (char *)&oob, NULL)) < 0) {
printk(KERN_NOTICE "Read of bad sector table failed (err %d)\n",
ret);
+ kfree(nftl->ReplUnitTable);
+ kfree(nftl->EUNtable);
return -1;
}
}
/* mark the Bad Erase Unit as RESERVED in ReplUnitTable */
if (buf[i & (SECTORSIZE - 1)] != 0xff)
nftl->ReplUnitTable[i] = BLOCK_RESERVED;
+#endif
+ if (nftl->mbd.mtd->block_isbad(nftl->mbd.mtd, i * nftl->EraseSize))
+ nftl->ReplUnitTable[i] = BLOCK_RESERVED;
}
-
+
nftl->MediaUnit = block;
boot_record_count++;
-
+
} /* foreach (block) */
-
+
return boot_record_count?0:-1;
}
@@ -209,25 +265,21 @@ static int memcmpb(void *a, int c, int n)
}
/* check_free_sector: check if a free sector is actually FREE, i.e. All 0xff in data and oob area */
-static int check_free_sectors(struct NFTLrecord *nftl, unsigned int address, int len,
+static int check_free_sectors(struct NFTLrecord *nftl, unsigned int address, int len,
int check_oob)
{
- int i, retlen;
- u8 buf[SECTORSIZE];
+ int i;
+ size_t retlen;
+ u8 buf[SECTORSIZE + nftl->mbd.mtd->oobsize];
for (i = 0; i < len; i += SECTORSIZE) {
- /* we want to read the sector without ECC check here since a free
- sector does not have ECC syndrome on it yet */
- if (MTD_READ(nftl->mtd, address, SECTORSIZE, &retlen, buf) < 0)
+ if (MTD_READECC(nftl->mbd.mtd, address, SECTORSIZE, &retlen, buf, &buf[SECTORSIZE], &nftl->oobinfo) < 0)
return -1;
if (memcmpb(buf, 0xff, SECTORSIZE) != 0)
return -1;
if (check_oob) {
- if (MTD_READOOB(nftl->mtd, address, nftl->mtd->oobsize,
- &retlen, buf) < 0)
- return -1;
- if (memcmpb(buf, 0xff, nftl->mtd->oobsize) != 0)
+ if (memcmpb(buf + SECTORSIZE, 0xff, nftl->mbd.mtd->oobsize) != 0)
return -1;
}
address += SECTORSIZE;
@@ -241,18 +293,17 @@ static int check_free_sectors(struct NFTLrecord *nftl, unsigned int address, int
*
* Return: 0 when succeed, -1 on error.
*
- * ToDo: 1. Is it neceressary to check_free_sector after erasing ??
- * 2. UnitSizeFactor != 0xFF
+ * ToDo: 1. Is it neceressary to check_free_sector after erasing ??
*/
int NFTL_formatblock(struct NFTLrecord *nftl, int block)
{
- int retlen;
+ size_t retlen;
unsigned int nb_erases, erase_mark;
struct nftl_uci1 uci;
struct erase_info *instr = &nftl->instr;
/* Read the Unit Control Information #1 for Wear-Leveling */
- if (MTD_READOOB(nftl->mtd, block * nftl->EraseSize + SECTORSIZE + 8,
+ if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8,
8, &retlen, (char *)&uci) < 0)
goto default_uci1;
@@ -267,16 +318,16 @@ int NFTL_formatblock(struct NFTLrecord *nftl, int block)
memset(instr, 0, sizeof(struct erase_info));
/* XXX: use async erase interface, XXX: test return code */
+ instr->mtd = nftl->mbd.mtd;
instr->addr = block * nftl->EraseSize;
instr->len = nftl->EraseSize;
- MTD_ERASE(nftl->mtd, instr);
+ MTD_ERASE(nftl->mbd.mtd, instr);
if (instr->state == MTD_ERASE_FAILED) {
- /* could not format, FixMe: We should update the BadUnitTable
- both in memory and on disk */
printk("Error while formatting block %d\n", block);
- return -1;
- } else {
+ goto fail;
+ }
+
/* increase and write Wear-Leveling info */
nb_erases = le32_to_cpu(uci.WearInfo);
nb_erases++;
@@ -289,14 +340,18 @@ int NFTL_formatblock(struct NFTLrecord *nftl, int block)
* FixMe: is this check really necessary ? since we have check the
* return code after the erase operation. */
if (check_free_sectors(nftl, instr->addr, nftl->EraseSize, 1) != 0)
- return -1;
+ goto fail;
uci.WearInfo = le32_to_cpu(nb_erases);
- if (MTD_WRITEOOB(nftl->mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8,
+ if (MTD_WRITEOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8,
&retlen, (char *)&uci) < 0)
- return -1;
+ goto fail;
return 0;
- }
+fail:
+ /* could not format, update the bad block table (caller is responsible
+ for setting the ReplUnitTable to BLOCK_RESERVED on failure) */
+ nftl->mbd.mtd->block_markbad(nftl->mbd.mtd, instr->addr);
+ return -1;
}
/* check_sectors_in_chain: Check that each sector of a Virtual Unit Chain is correct.
@@ -312,13 +367,14 @@ static void check_sectors_in_chain(struct NFTLrecord *nftl, unsigned int first_b
{
unsigned int block, i, status;
struct nftl_bci bci;
- int sectors_per_block, retlen;
+ int sectors_per_block;
+ size_t retlen;
sectors_per_block = nftl->EraseSize / SECTORSIZE;
block = first_block;
for (;;) {
for (i = 0; i < sectors_per_block; i++) {
- if (MTD_READOOB(nftl->mtd, block * nftl->EraseSize + i * SECTORSIZE,
+ if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + i * SECTORSIZE,
8, &retlen, (char *)&bci) < 0)
status = SECTOR_IGNORE;
else
@@ -329,7 +385,7 @@ static void check_sectors_in_chain(struct NFTLrecord *nftl, unsigned int first_b
/* verify that the sector is really free. If not, mark
as ignore */
if (memcmpb(&bci, 0xff, 8) != 0 ||
- check_free_sectors(nftl, block * nftl->EraseSize + i * SECTORSIZE,
+ check_free_sectors(nftl, block * nftl->EraseSize + i * SECTORSIZE,
SECTORSIZE, 0) != 0) {
printk("Incorrect free sector %d in block %d: "
"marking it as ignored\n",
@@ -338,7 +394,7 @@ static void check_sectors_in_chain(struct NFTLrecord *nftl, unsigned int first_b
/* sector not free actually : mark it as SECTOR_IGNORE */
bci.Status = SECTOR_IGNORE;
bci.Status1 = SECTOR_IGNORE;
- MTD_WRITEOOB(nftl->mtd,
+ MTD_WRITEOOB(nftl->mbd.mtd,
block * nftl->EraseSize + i * SECTORSIZE,
8, &retlen, (char *)&bci);
}
@@ -401,8 +457,7 @@ static void format_chain(struct NFTLrecord *nftl, unsigned int first_block)
printk("Formatting block %d\n", block);
if (NFTL_formatblock(nftl, block) < 0) {
- /* cannot format !!!! Mark it as Bad Unit,
- FixMe: update the BadUnitTable on disk */
+ /* cannot format !!!! Mark it as Bad Unit */
nftl->ReplUnitTable[block] = BLOCK_RESERVED;
} else {
nftl->ReplUnitTable[block] = BLOCK_FREE;
@@ -428,10 +483,10 @@ static int check_and_mark_free_block(struct NFTLrecord *nftl, int block)
{
struct nftl_uci1 h1;
unsigned int erase_mark;
- int retlen;
+ size_t retlen;
/* check erase mark. */
- if (MTD_READOOB(nftl->mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8,
+ if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8,
&retlen, (char *)&h1) < 0)
return -1;
@@ -446,7 +501,7 @@ static int check_and_mark_free_block(struct NFTLrecord *nftl, int block)
h1.EraseMark = cpu_to_le16(ERASE_MARK);
h1.EraseMark1 = cpu_to_le16(ERASE_MARK);
h1.WearInfo = cpu_to_le32(0);
- if (MTD_WRITEOOB(nftl->mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8,
+ if (MTD_WRITEOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8,
&retlen, (char *)&h1) < 0)
return -1;
} else {
@@ -458,7 +513,7 @@ static int check_and_mark_free_block(struct NFTLrecord *nftl, int block)
SECTORSIZE, 0) != 0)
return -1;
- if (MTD_READOOB(nftl->mtd, block * nftl->EraseSize + i,
+ if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + i,
16, &retlen, buf) < 0)
return -1;
if (i == SECTORSIZE) {
@@ -486,9 +541,9 @@ static int check_and_mark_free_block(struct NFTLrecord *nftl, int block)
static int get_fold_mark(struct NFTLrecord *nftl, unsigned int block)
{
struct nftl_uci2 uci;
- int retlen;
+ size_t retlen;
- if (MTD_READOOB(nftl->mtd, block * nftl->EraseSize + 2 * SECTORSIZE + 8,
+ if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + 2 * SECTORSIZE + 8,
8, &retlen, (char *)&uci) < 0)
return 0;
@@ -503,44 +558,14 @@ int NFTL_mount(struct NFTLrecord *s)
int chain_length, do_format_chain;
struct nftl_uci0 h0;
struct nftl_uci1 h1;
- int retlen;
-
- /* XXX: will be suppressed */
- s->lastEUN = s->nb_blocks - 1;
-
- /* memory alloc */
- s->EUNtable = kmalloc(s->nb_blocks * sizeof(u16), GFP_KERNEL);
- s->ReplUnitTable = kmalloc(s->nb_blocks * sizeof(u16), GFP_KERNEL);
- if (!s->EUNtable || !s->ReplUnitTable) {
- fail:
- if (s->EUNtable)
- kfree(s->EUNtable);
- if (s->ReplUnitTable)
- kfree(s->ReplUnitTable);
- return -1;
- }
-
- /* mark all blocks as potentially containing data */
- for (i = 0; i < s->nb_blocks; i++) {
- s->ReplUnitTable[i] = BLOCK_NOTEXPLORED;
- }
+ size_t retlen;
/* search for NFTL MediaHeader and Spare NFTL Media Header */
if (find_boot_record(s) < 0) {
printk("Could not find valid boot record\n");
- goto fail;
+ return -1;
}
- /* mark the bios blocks (blocks before NFTL MediaHeader) as reserved */
- for (i = 0; i < s->nb_boot_blocks; i++)
- s->ReplUnitTable[i] = BLOCK_RESERVED;
-
- /* also mark the boot records (NFTL MediaHeader) blocks as reserved */
- if (s->MediaUnit != BLOCK_NIL)
- s->ReplUnitTable[s->MediaUnit] = BLOCK_RESERVED;
- if (s->SpareMediaUnit != BLOCK_NIL)
- s->ReplUnitTable[s->SpareMediaUnit] = BLOCK_RESERVED;
-
/* init the logical to physical table */
for (i = 0; i < s->nb_blocks; i++) {
s->EUNtable[i] = BLOCK_NIL;
@@ -557,9 +582,9 @@ int NFTL_mount(struct NFTLrecord *s)
for (;;) {
/* read the block header. If error, we format the chain */
- if (MTD_READOOB(s->mtd, block * s->EraseSize + 8, 8,
+ if (MTD_READOOB(s->mbd.mtd, block * s->EraseSize + 8, 8,
&retlen, (char *)&h0) < 0 ||
- MTD_READOOB(s->mtd, block * s->EraseSize + SECTORSIZE + 8, 8,
+ MTD_READOOB(s->mbd.mtd, block * s->EraseSize + SECTORSIZE + 8, 8,
&retlen, (char *)&h1) < 0) {
s->ReplUnitTable[block] = BLOCK_NIL;
do_format_chain = 1;
@@ -614,7 +639,7 @@ int NFTL_mount(struct NFTLrecord *s)
first_logical_block = logical_block;
} else {
if (logical_block != first_logical_block) {
- printk("Block %d: incorrect logical block: %d expected: %d\n",
+ printk("Block %d: incorrect logical block: %d expected: %d\n",
block, logical_block, first_logical_block);
/* the chain is incorrect : we must format it,
but we need to read it completly */
@@ -643,7 +668,7 @@ int NFTL_mount(struct NFTLrecord *s)
s->ReplUnitTable[block] = BLOCK_NIL;
break;
} else if (rep_block >= s->nb_blocks) {
- printk("Block %d: referencing invalid block %d\n",
+ printk("Block %d: referencing invalid block %d\n",
block, rep_block);
do_format_chain = 1;
s->ReplUnitTable[block] = BLOCK_NIL;
@@ -663,7 +688,7 @@ int NFTL_mount(struct NFTLrecord *s)
s->ReplUnitTable[block] = rep_block;
s->EUNtable[first_logical_block] = BLOCK_NIL;
} else {
- printk("Block %d: referencing block %d already in another chain\n",
+ printk("Block %d: referencing block %d already in another chain\n",
block, rep_block);
/* XXX: should handle correctly fold in progress chains */
do_format_chain = 1;
@@ -685,7 +710,7 @@ int NFTL_mount(struct NFTLrecord *s)
} else {
unsigned int first_block1, chain_to_format, chain_length1;
int fold_mark;
-
+
/* valid chain : get foldmark */
fold_mark = get_fold_mark(s, first_block);
if (fold_mark == 0) {
@@ -704,9 +729,9 @@ int NFTL_mount(struct NFTLrecord *s)
if (first_block1 != BLOCK_NIL) {
/* XXX: what to do if same length ? */
chain_length1 = calc_chain_length(s, first_block1);
- printk("Two chains at blocks %d (len=%d) and %d (len=%d)\n",
+ printk("Two chains at blocks %d (len=%d) and %d (len=%d)\n",
first_block1, chain_length1, first_block, chain_length);
-
+
if (chain_length >= chain_length1) {
chain_to_format = first_block1;
s->EUNtable[first_logical_block] = first_block;
@@ -725,7 +750,7 @@ int NFTL_mount(struct NFTLrecord *s)
/* second pass to format unreferenced blocks and init free block count */
s->numfreeEUNs = 0;
- s->LastFreeEUN = BLOCK_NIL;
+ s->LastFreeEUN = le16_to_cpu(s->MediaHdr.FirstPhysicalEUN);
for (block = 0; block < s->nb_blocks; block++) {
if (s->ReplUnitTable[block] == BLOCK_NOTEXPLORED) {