patch-2.4.21 linux-2.4.21/drivers/mtd/nftlmount.c
Next file: linux-2.4.21/drivers/net/3c501.c
Previous file: linux-2.4.21/drivers/mtd/nftlcore.c
Back to the patch index
Back to the overall index
- Lines: 239
- Date:
2003-06-13 07:51:34.000000000 -0700
- Orig file:
linux-2.4.20/drivers/mtd/nftlmount.c
- Orig date:
2002-02-25 11:37:58.000000000 -0800
diff -urN linux-2.4.20/drivers/mtd/nftlmount.c linux-2.4.21/drivers/mtd/nftlmount.c
@@ -4,7 +4,7 @@
* 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.31 2002/11/15 16:34:43 dwmw2 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
@@ -34,12 +34,13 @@
#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.31 $";
/* 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
@@ -51,11 +52,16 @@
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 */
+ nftl->EraseSize = nftl->mtd->erasesize;
+ nftl->nb_blocks = nftl->mtd->size / nftl->EraseSize;
+
nftl->MediaUnit = BLOCK_NIL;
nftl->SpareMediaUnit = BLOCK_NIL;
@@ -88,7 +94,7 @@
/* To be safer with BIOS, also use erase mark as discriminant */
if ((ret = MTD_READOOB(nftl->mtd, block * nftl->EraseSize + SECTORSIZE + 8,
- 8, &retlen, (char *)&h1) < 0)) {
+ 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);
continue;
@@ -107,7 +113,7 @@
/* Finally reread to check ECC */
if ((ret = MTD_READECC(nftl->mtd, block * nftl->EraseSize, SECTORSIZE,
- &retlen, buf, (char *)&oob) < 0)) {
+ &retlen, buf, (char *)&oob, NAND_ECC_DISKONCHIP)) < 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);
continue;
@@ -122,7 +128,6 @@
continue;
}
#endif
-
/* OK, we like it. */
if (boot_record_count) {
@@ -137,6 +142,10 @@
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,12 +154,18 @@
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 (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->mtd->erasesize << (0xff - mh->UnitSizeFactor);
+ nftl->nb_blocks = nftl->mtd->size / nftl->EraseSize;
}
-
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");
@@ -168,20 +183,50 @@
}
nftl->nr_sects = 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 ((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) {
+ i + SECTORSIZE, SECTORSIZE, &retlen, buf,
+ (char *)&oob, NAND_ECC_DISKONCHIP)) < 0) {
printk(KERN_NOTICE "Read of bad sector table failed (err %d)\n",
ret);
+ kfree(nftl->ReplUnitTable);
+ kfree(nftl->EUNtable);
return -1;
}
}
@@ -246,7 +291,7 @@
*/
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;
@@ -428,7 +473,7 @@
{
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,
@@ -486,7 +531,7 @@
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,
8, &retlen, (char *)&uci) < 0)
@@ -503,44 +548,14 @@
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;
@@ -725,7 +740,7 @@
/* 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) {
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)