mtd/drivers/mtd nftlmount.c,1.32,1.33 nftlcore.c,1.88,1.89
David Woodhouse
dwmw2 at infradead.org
Sun May 18 18:29:51 EDT 2003
Update of /home/cvs/mtd/drivers/mtd
In directory phoenix.infradead.org:/tmp/cvs-serv15157
Modified Files:
nftlmount.c nftlcore.c
Log Message:
Convert NFTL to blktrans (untested)
Index: nftlmount.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/nftlmount.c,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -r1.32 -r1.33
--- nftlmount.c 9 May 2003 22:34:12 -0000 1.32
+++ nftlmount.c 18 May 2003 22:29:47 -0000 1.33
@@ -59,8 +59,8 @@
/* 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->EraseSize = nftl->mbd.mtd->erasesize;
+ nftl->nb_blocks = nftl->mbd.mtd->size / nftl->EraseSize;
nftl->MediaUnit = BLOCK_NIL;
nftl->SpareMediaUnit = BLOCK_NIL;
@@ -71,12 +71,12 @@
/* 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))) {
+ if ((ret = MTD_READ(nftl->mbd.mtd, block * nftl->EraseSize, SECTORSIZE, &retlen, buf))) {
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");
}
@@ -87,16 +87,16 @@
/* 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);
+ 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;
}
@@ -106,23 +106,23 @@
*/
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,
+ if ((ret = MTD_READECC(nftl->mbd.mtd, block * nftl->EraseSize, SECTORSIZE,
&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);
+ 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;
@@ -167,8 +167,8 @@
} 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->EraseSize = nftl->mbd.mtd->erasesize << (0xff - mh->UnitSizeFactor);
+ nftl->nb_blocks = nftl->mbd.mtd->size / nftl->EraseSize;
}
nftl->nb_boot_blocks = le16_to_cpu(mh->FirstPhysicalEUN);
if ((nftl->nb_boot_blocks + 2) >= nftl->nb_blocks) {
@@ -186,7 +186,7 @@
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 */
@@ -224,7 +224,7 @@
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 +
+ if ((ret = MTD_READECC(nftl->mbd.mtd, block * nftl->EraseSize +
i + SECTORSIZE, SECTORSIZE, &retlen, buf,
(char *)&oob, NAND_ECC_DISKONCHIP)) < 0) {
printk(KERN_NOTICE "Read of bad sector table failed (err %d)\n",
@@ -267,16 +267,16 @@
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_READ(nftl->mbd.mtd, address, SECTORSIZE, &retlen, buf) < 0)
return -1;
if (memcmpb(buf, 0xff, SECTORSIZE) != 0)
return -1;
if (check_oob) {
- if (MTD_READOOB(nftl->mtd, address, nftl->mtd->oobsize,
+ if (MTD_READOOB(nftl->mbd.mtd, address, nftl->mbd.mtd->oobsize,
&retlen, buf) < 0)
return -1;
- if (memcmpb(buf, 0xff, nftl->mtd->oobsize) != 0)
+ if (memcmpb(buf, 0xff, nftl->mbd.mtd->oobsize) != 0)
return -1;
}
address += SECTORSIZE;
@@ -301,7 +301,7 @@
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;
@@ -318,7 +318,7 @@
/* XXX: use async erase interface, XXX: test return code */
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
@@ -341,7 +341,7 @@
return -1;
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;
return 0;
@@ -367,7 +367,7 @@
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
@@ -387,7 +387,7 @@
/* 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);
}
@@ -480,7 +480,7 @@
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;
@@ -495,7 +495,7 @@
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 {
@@ -507,7 +507,7 @@
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) {
@@ -537,7 +537,7 @@
struct nftl_uci2 uci;
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;
@@ -576,9 +576,9 @@
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;
Index: nftlcore.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/nftlcore.c,v
retrieving revision 1.88
retrieving revision 1.89
diff -u -r1.88 -r1.89
--- nftlcore.c 2 Mar 2003 18:45:07 -0000 1.88
+++ nftlcore.c 18 May 2003 22:29:47 -0000 1.89
@@ -23,15 +23,13 @@
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/init.h>
-#include <linux/blkpg.h>
+#include <linux/hdreg.h>
-#ifdef CONFIG_KMOD
#include <linux/kmod.h>
-#endif
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/nftl.h>
-#include <linux/mtd/compatmac.h>
+#include <linux/mtd/blktrans.h>
/* maximum number of loops while examining next block, to have a
chance to detect consistency problems (they should never happen
@@ -39,87 +37,29 @@
#define MAX_LOOPS 10000
-/* NFTL block device stuff */
-#define MAJOR_NR NFTL_MAJOR
-#define DEVICE_REQUEST nftl_request
-#define DEVICE_OFF(device)
-
-
-#include <linux/blk.h>
-#include <linux/hdreg.h>
-
-/* Linux-specific block device functions */
-
-/* I _HATE_ the Linux block device setup more than anything else I've ever
- * encountered, except ...
- */
-
-static int nftl_sizes[256];
-static int nftl_blocksizes[256];
-
-/* .. for the Linux partition table handling. */
-struct hd_struct part_table[256];
-
-#if LINUX_VERSION_CODE < 0x20328
-static void dummy_init (struct gendisk *crap)
-{}
-#endif
-
-static struct gendisk nftl_gendisk = {
- major: MAJOR_NR,
- major_name: "nftl",
- minor_shift: NFTL_PARTN_BITS, /* Bits to shift to get real from partition */
- max_p: (1<<NFTL_PARTN_BITS)-1, /* Number of partitions per real */
-#if LINUX_VERSION_CODE < 0x20328
- max_nr: MAX_NFTLS, /* maximum number of real */
- init: dummy_init, /* init function */
-#endif
- part: part_table, /* hd struct */
- sizes: nftl_sizes, /* block sizes */
-};
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,14)
-#define BLK_INC_USE_COUNT MOD_INC_USE_COUNT
-#define BLK_DEC_USE_COUNT MOD_DEC_USE_COUNT
-#else
-#define BLK_INC_USE_COUNT do {} while(0)
-#define BLK_DEC_USE_COUNT do {} while(0)
-#endif
-
-struct NFTLrecord *NFTLs[MAX_NFTLS];
-static void NFTL_setup(struct mtd_info *mtd)
+static void nftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
{
- int i;
struct NFTLrecord *nftl;
unsigned long temp;
- int firstfree = -1;
-
- DEBUG(MTD_DEBUG_LEVEL1,"NFTL_setup\n");
- for (i = 0; i < MAX_NFTLS; i++) {
- if (!NFTLs[i] && firstfree == -1)
- firstfree = i;
- else if (NFTLs[i] && NFTLs[i]->mtd == mtd) {
- /* This is a Spare Media Header for an NFTL we've already found */
- DEBUG(MTD_DEBUG_LEVEL1, "MTD already mounted as NFTL\n");
- return;
- }
- }
- if (firstfree == -1) {
- printk(KERN_WARNING "No more NFTL slot available\n");
+ if (mtd->ecctype != MTD_ECC_RS_DiskOnChip)
return;
- }
+
+ DEBUG(MTD_DEBUG_LEVEL1, "nftl_add_mtd for %s\n", mtd->name);
nftl = kmalloc(sizeof(struct NFTLrecord), GFP_KERNEL);
+
if (!nftl) {
printk(KERN_WARNING "Out of memory for NFTL data structures\n");
return;
}
+ memset(nftl, 0, sizeof(*nftl));
- init_MUTEX(&nftl->mutex);
-
- nftl->mtd = mtd;
+ nftl->mbd.mtd = mtd;
+ nftl->mbd.devnum = -1;
+ nftl->mbd.blksize = 512;
+ nftl->mbd.tr = tr;
if (NFTL_mount(nftl) < 0) {
printk(KERN_WARNING "Could not mount NFTL device\n");
@@ -128,100 +68,65 @@
}
/* OK, it's a new one. Set up all the data structures. */
-#ifdef PSYCHO_DEBUG
- printk("Found new NFTL nftl%c\n", firstfree + 'a');
-#endif
- /* linux stuff */
- nftl->usecount = 0;
+ /* Calculate geometry */
nftl->cylinders = 1024;
nftl->heads = 16;
temp = nftl->cylinders * nftl->heads;
- nftl->sectors = nftl->nr_sects / temp;
- if (nftl->nr_sects % temp) {
+ nftl->sectors = nftl->mbd.size / temp;
+ if (nftl->mbd.size % temp) {
nftl->sectors++;
temp = nftl->cylinders * nftl->sectors;
- nftl->heads = nftl->nr_sects / temp;
+ nftl->heads = nftl->mbd.size / temp;
- if (nftl->nr_sects % temp) {
+ if (nftl->mbd.size % temp) {
nftl->heads++;
temp = nftl->heads * nftl->sectors;
- nftl->cylinders = nftl->nr_sects / temp;
+ nftl->cylinders = nftl->mbd.size / temp;
}
}
- if (nftl->nr_sects != nftl->heads * nftl->cylinders * nftl->sectors) {
+ if (nftl->mbd.size != nftl->heads * nftl->cylinders * nftl->sectors) {
+ /*
+ Oh no we don't have
+ mbd.size == heads * cylinders * sectors
+ */
printk(KERN_WARNING "Cannot calculate an NFTL geometry to "
- "match size of 0x%x.\n", nftl->nr_sects);
+ "precisely match size of 0x%lx.\n", nftl->mbd.size);
printk(KERN_WARNING "Using C:%d H:%d S:%d (== 0x%lx sects)\n",
nftl->cylinders, nftl->heads , nftl->sectors,
(long)nftl->cylinders * (long)nftl->heads * (long)nftl->sectors );
+ }
- /* Oh no we don't have nftl->nr_sects = nftl->heads * nftl->cylinders * nftl->sectors; */
+ if (add_mtd_blktrans_dev) {
+ if (nftl->ReplUnitTable)
+ kfree(nftl->ReplUnitTable);
+ if (nftl->EUNtable)
+ kfree(nftl->EUNtable);
+ kfree(nftl);
+ return;
}
- NFTLs[firstfree] = nftl;
- /* Finally, set up the block device sizes */
- nftl_sizes[firstfree * 16] = nftl->nr_sects;
- //nftl_blocksizes[firstfree*16] = 512;
- part_table[firstfree * 16].nr_sects = nftl->nr_sects;
-
- nftl_gendisk.nr_real++;
-
- /* partition check ... */
-#if LINUX_VERSION_CODE < 0x20328
- resetup_one_dev(&nftl_gendisk, firstfree);
-#else
- grok_partitions(&nftl_gendisk, firstfree, 1<<NFTL_PARTN_BITS, nftl->nr_sects);
+#ifdef PSYCHO_DEBUG
+ printk("Found new NFTL nftl%c\n", nftl->mbd.devnum + 'a');
#endif
+ return;
}
-static void NFTL_unsetup(int i)
+static void nftl_remove_dev(struct mtd_blktrans_dev *dev)
{
- struct NFTLrecord *nftl = NFTLs[i];
+ struct NFTLrecord *nftl = (void *)dev;
- DEBUG(MTD_DEBUG_LEVEL1, "NFTL_unsetup %d\n", i);
-
- NFTLs[i] = NULL;
-
+ DEBUG(MTD_DEBUG_LEVEL1, "nftl_remove_dev %d\n", dev->devnum);
+
+ del_mtd_blktrans_dev(dev);
if (nftl->ReplUnitTable)
kfree(nftl->ReplUnitTable);
if (nftl->EUNtable)
kfree(nftl->EUNtable);
-
- nftl_gendisk.nr_real--;
kfree(nftl);
}
-/* Search the MTD device for NFTL partitions */
-static void NFTL_notify_add(struct mtd_info *mtd)
-{
- DEBUG(MTD_DEBUG_LEVEL1, "NFTL_notify_add for %s\n", mtd->name);
-
- if (mtd) {
- if (!mtd->read_oob) {
- /* If this MTD doesn't have out-of-band data,
- then there's no point continuing */
- DEBUG(MTD_DEBUG_LEVEL1, "No OOB data, quitting\n");
- return;
- }
- DEBUG(MTD_DEBUG_LEVEL3, "mtd->read = %p, size = %d, erasesize = %d\n",
- mtd->read, mtd->size, mtd->erasesize);
-
- NFTL_setup(mtd);
- }
-}
-
-static void NFTL_notify_remove(struct mtd_info *mtd)
-{
- int i;
-
- for (i = 0; i < MAX_NFTLS; i++) {
- if (NFTLs[i] && NFTLs[i]->mtd == mtd)
- NFTL_unsetup(i);
- }
-}
-
#ifdef CONFIG_NFTL_RW
/* Actual NFTL access routines */
@@ -303,7 +208,7 @@
targetEUN = thisEUN;
for (block = 0; block < nftl->EraseSize / 512; block ++) {
- MTD_READOOB(nftl->mtd,
+ MTD_READOOB(nftl->mbd.mtd,
(thisEUN * nftl->EraseSize) + (block * 512),
16 , &retlen, (char *)&oob);
if (block == 2) {
@@ -420,7 +325,7 @@
chain by selecting the longer one */
oob.u.c.FoldMark = oob.u.c.FoldMark1 = cpu_to_le16(FOLD_MARK_IN_PROGRESS);
oob.u.c.unused = 0xffffffff;
- MTD_WRITEOOB(nftl->mtd, (nftl->EraseSize * targetEUN) + 2 * 512 + 8,
+ MTD_WRITEOOB(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) + 2 * 512 + 8,
8, &retlen, (char *)&oob.u);
}
@@ -444,16 +349,16 @@
if (BlockMap[block] == BLOCK_NIL)
continue;
- ret = MTD_READECC(nftl->mtd, (nftl->EraseSize * BlockMap[block]) + (block * 512),
+ ret = MTD_READECC(nftl->mbd.mtd, (nftl->EraseSize * BlockMap[block]) + (block * 512),
512, &retlen, movebuf, (char *)&oob, NAND_ECC_DISKONCHIP);
if (ret < 0) {
- ret = MTD_READECC(nftl->mtd, (nftl->EraseSize * BlockMap[block])
+ ret = MTD_READECC(nftl->mbd.mtd, (nftl->EraseSize * BlockMap[block])
+ (block * 512), 512, &retlen,
movebuf, (char *)&oob, NAND_ECC_DISKONCHIP);
if (ret != -EIO)
printk("Error went away on retry.\n");
}
- MTD_WRITEECC(nftl->mtd, (nftl->EraseSize * targetEUN) + (block * 512),
+ MTD_WRITEECC(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) + (block * 512),
512, &retlen, movebuf, (char *)&oob, NAND_ECC_DISKONCHIP);
}
@@ -462,7 +367,7 @@
= cpu_to_le16(thisVUC);
oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = 0xffff;
- MTD_WRITEOOB(nftl->mtd, (nftl->EraseSize * targetEUN) + 8,
+ MTD_WRITEOOB(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) + 8,
8, &retlen, (char *)&oob.u);
/* OK. We've moved the whole lot into the new block. Now we have to free the original blocks. */
@@ -582,7 +487,7 @@
lastEUN = writeEUN;
- MTD_READOOB(nftl->mtd, (writeEUN * nftl->EraseSize) + blockofs,
+ MTD_READOOB(nftl->mbd.mtd, (writeEUN * nftl->EraseSize) + blockofs,
8, &retlen, (char *)&bci);
DEBUG(MTD_DEBUG_LEVEL2, "Status of block %d in EUN %d is %x\n",
@@ -670,12 +575,12 @@
nftl->ReplUnitTable[writeEUN] = BLOCK_NIL;
/* ... and on the flash itself */
- MTD_READOOB(nftl->mtd, writeEUN * nftl->EraseSize + 8, 8,
+ MTD_READOOB(nftl->mbd.mtd, writeEUN * nftl->EraseSize + 8, 8,
&retlen, (char *)&oob.u);
oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC);
- MTD_WRITEOOB(nftl->mtd, writeEUN * nftl->EraseSize + 8, 8,
+ MTD_WRITEOOB(nftl->mbd.mtd, writeEUN * nftl->EraseSize + 8, 8,
&retlen, (char *)&oob.u);
/* we link the new block to the chain only after the
@@ -685,13 +590,13 @@
/* Both in our cache... */
nftl->ReplUnitTable[lastEUN] = writeEUN;
/* ... and on the flash itself */
- MTD_READOOB(nftl->mtd, (lastEUN * nftl->EraseSize) + 8,
+ MTD_READOOB(nftl->mbd.mtd, (lastEUN * nftl->EraseSize) + 8,
8, &retlen, (char *)&oob.u);
oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum
= cpu_to_le16(writeEUN);
- MTD_WRITEOOB(nftl->mtd, (lastEUN * nftl->EraseSize) + 8,
+ MTD_WRITEOOB(nftl->mbd.mtd, (lastEUN * nftl->EraseSize) + 8,
8, &retlen, (char *)&oob.u);
}
@@ -704,8 +609,10 @@
return 0xffff;
}
-static int NFTL_writeblock(struct NFTLrecord *nftl, unsigned block, char *buffer)
+static int nftl_writeblock(struct mtd_blktrans_dev *mbd, unsigned long block,
+ char *buffer)
{
+ struct NFTLrecord *nftl = (void *)mbd;
u16 writeEUN;
unsigned long blockofs = (block * 512) & (nftl->EraseSize - 1);
size_t retlen;
@@ -720,7 +627,7 @@
return 1;
}
- MTD_WRITEECC(nftl->mtd, (writeEUN * nftl->EraseSize) + blockofs,
+ MTD_WRITEECC(nftl->mbd.mtd, (writeEUN * nftl->EraseSize) + blockofs,
512, &retlen, (char *)buffer, (char *)eccbuf, NAND_ECC_DISKONCHIP);
/* no need to write SECTOR_USED flags since they are written in mtd_writeecc */
@@ -728,8 +635,10 @@
}
#endif /* CONFIG_NFTL_RW */
-static int NFTL_readblock(struct NFTLrecord *nftl, unsigned block, char *buffer)
+static int nftl_readblock(struct mtd_blktrans_dev *mbd, unsigned long block,
+ char *buffer)
{
+ struct NFTLrecord *nftl = (void *)mbd;
u16 lastgoodEUN;
u16 thisEUN = nftl->EUNtable[block / (nftl->EraseSize / 512)];
unsigned long blockofs = (block * 512) & (nftl->EraseSize - 1);
@@ -742,7 +651,7 @@
if (thisEUN != BLOCK_NIL) {
while (thisEUN < nftl->nb_blocks) {
- if (MTD_READOOB(nftl->mtd, (thisEUN * nftl->EraseSize) + blockofs,
+ if (MTD_READOOB(nftl->mbd.mtd, (thisEUN * nftl->EraseSize) + blockofs,
8, &retlen, (char *)&bci) < 0)
status = SECTOR_IGNORE;
else
@@ -761,13 +670,13 @@
case SECTOR_IGNORE:
break;
default:
- printk("Unknown status for block %d in EUN %d: %x\n",
+ printk("Unknown status for block %ld in EUN %d: %x\n",
block, thisEUN, status);
break;
}
if (!silly--) {
- printk(KERN_WARNING "Infinite loop in Virtual Unit Chain 0x%x\n",
+ printk(KERN_WARNING "Infinite loop in Virtual Unit Chain 0x%lx\n",
block / (nftl->EraseSize / 512));
return 1;
}
@@ -783,20 +692,17 @@
loff_t ptr = (lastgoodEUN * nftl->EraseSize) + blockofs;
size_t retlen;
u_char eccbuf[6];
- if (MTD_READECC(nftl->mtd, ptr, 512, &retlen, buffer, eccbuf, NAND_ECC_DISKONCHIP))
+ if (MTD_READECC(nftl->mbd.mtd, ptr, 512, &retlen, buffer, eccbuf, NAND_ECC_DISKONCHIP))
return -EIO;
}
return 0;
}
-static int nftl_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg)
+static int nftl_ioctl(struct mtd_blktrans_dev *dev,
+ struct inode * inode, struct file * file,
+ unsigned int cmd, unsigned long arg)
{
- struct NFTLrecord *nftl;
- int p;
-
- nftl = NFTLs[MINOR(inode->i_rdev) >> NFTL_PARTN_BITS];
-
- if (!nftl) return -EINVAL;
+ struct NFTLrecord *nftl = (void *)dev;
switch (cmd) {
case HDIO_GETGEO: {
@@ -805,242 +711,18 @@
g.heads = nftl->heads;
g.sectors = nftl->sectors;
g.cylinders = nftl->cylinders;
- g.start = part_table[MINOR(inode->i_rdev)].start_sect;
+ g.start = 0;
return copy_to_user((void *)arg, &g, sizeof g) ? -EFAULT : 0;
}
- case BLKGETSIZE: /* Return device size */
- return put_user(part_table[MINOR(inode->i_rdev)].nr_sects,
- (unsigned long *) arg);
-
-#ifdef BLKGETSIZE64
- case BLKGETSIZE64:
- return put_user((u64)part_table[MINOR(inode->i_rdev)].nr_sects << 9,
- (u64 *)arg);
-#endif
case BLKFLSBUF:
- if (!capable(CAP_SYS_ADMIN)) return -EACCES;
- fsync_dev(inode->i_rdev);
- invalidate_buffers(inode->i_rdev);
- if (nftl->mtd->sync)
- nftl->mtd->sync(nftl->mtd);
return 0;
- case BLKRRPART:
- if (!capable(CAP_SYS_ADMIN)) return -EACCES;
- if (nftl->usecount > 1) return -EBUSY;
- /*
- * We have to flush all buffers and invalidate caches,
- * or we won't be able to re-use the partitions,
- * if there was a change and we don't want to reboot
- */
- p = (1<<NFTL_PARTN_BITS) - 1;
- while (p-- > 0) {
- kdev_t devp = MKDEV(MAJOR(inode->i_dev), MINOR(inode->i_dev)+p);
- if (part_table[p].nr_sects > 0)
- invalidate_device (devp, 1);
-
- part_table[MINOR(inode->i_dev)+p].start_sect = 0;
- part_table[MINOR(inode->i_dev)+p].nr_sects = 0;
- }
-
-#if LINUX_VERSION_CODE < 0x20328
- resetup_one_dev(&nftl_gendisk, MINOR(inode->i_rdev) >> NFTL_PARTN_BITS);
-#else
- grok_partitions(&nftl_gendisk, MINOR(inode->i_rdev) >> NFTL_PARTN_BITS,
- 1<<NFTL_PARTN_BITS, nftl->nr_sects);
-#endif
- return 0;
-
-#if (LINUX_VERSION_CODE < 0x20303)
- RO_IOCTLS(inode->i_rdev, arg); /* ref. linux/blk.h */
-#else
- case BLKROSET:
- case BLKROGET:
- case BLKSSZGET:
- return blk_ioctl(inode->i_rdev, cmd, arg);
-#endif
-
default:
- return -EINVAL;
- }
-}
-
-void nftl_request(RQFUNC_ARG)
-{
- unsigned int dev, block, nsect;
- struct NFTLrecord *nftl;
- char *buffer;
- struct request *req;
- int res;
-
- while (1) {
- INIT_REQUEST; /* blk.h */
- req = CURRENT;
-
- /* We can do this because the generic code knows not to
- touch the request at the head of the queue */
- spin_unlock_irq(&io_request_lock);
-
- DEBUG(MTD_DEBUG_LEVEL2, "NFTL_request\n");
- DEBUG(MTD_DEBUG_LEVEL3, "NFTL %s request, from sector 0x%04lx for 0x%04lx sectors\n",
- (req->cmd == READ) ? "Read " : "Write",
- req->sector, req->current_nr_sectors);
-
- dev = MINOR(req->rq_dev);
- block = req->sector;
- nsect = req->current_nr_sectors;
- buffer = req->buffer;
- res = 1; /* succeed */
-
- if (dev >= MAX_NFTLS * (1<<NFTL_PARTN_BITS)) {
- /* there is no such partition */
- printk("nftl: bad minor number: device = %s\n",
- kdevname(req->rq_dev));
- res = 0; /* fail */
- goto repeat;
- }
-
- nftl = NFTLs[dev / (1<<NFTL_PARTN_BITS)];
- DEBUG(MTD_DEBUG_LEVEL3, "Waiting for mutex\n");
- down(&nftl->mutex);
- DEBUG(MTD_DEBUG_LEVEL3, "Got mutex\n");
-
- if (block + nsect > part_table[dev].nr_sects) {
- /* access past the end of device */
- printk("nftl%c%d: bad access: block = %d, count = %d\n",
- (MINOR(req->rq_dev)>>6)+'a', dev & 0xf, block, nsect);
- up(&nftl->mutex);
- res = 0; /* fail */
- goto repeat;
- }
-
- block += part_table[dev].start_sect;
-
- if (req->cmd == READ) {
- DEBUG(MTD_DEBUG_LEVEL2, "NFTL read request of 0x%x sectors @ %x "
- "(req->nr_sectors == %lx)\n", nsect, block, req->nr_sectors);
-
- for ( ; nsect > 0; nsect-- , block++, buffer += 512) {
- /* Read a single sector to req->buffer + (512 * i) */
- if (NFTL_readblock(nftl, block, buffer)) {
- DEBUG(MTD_DEBUG_LEVEL2, "NFTL read request failed\n");
- up(&nftl->mutex);
- res = 0;
- goto repeat;
- }
- }
-
- DEBUG(MTD_DEBUG_LEVEL2,"NFTL read request completed OK\n");
- up(&nftl->mutex);
- goto repeat;
- } else if (req->cmd == WRITE) {
- DEBUG(MTD_DEBUG_LEVEL2, "NFTL write request of 0x%x sectors @ %x "
- "(req->nr_sectors == %lx)\n", nsect, block,
- req->nr_sectors);
-#ifdef CONFIG_NFTL_RW
- for ( ; nsect > 0; nsect-- , block++, buffer += 512) {
- /* Read a single sector to req->buffer + (512 * i) */
- if (NFTL_writeblock(nftl, block, buffer)) {
- DEBUG(MTD_DEBUG_LEVEL1,"NFTL write request failed\n");
- up(&nftl->mutex);
- res = 0;
- goto repeat;
- }
- }
- DEBUG(MTD_DEBUG_LEVEL2,"NFTL write request completed OK\n");
-#else
- res = 0; /* Writes always fail */
-#endif /* CONFIG_NFTL_RW */
- up(&nftl->mutex);
- goto repeat;
- } else {
- DEBUG(MTD_DEBUG_LEVEL0, "NFTL unknown request\n");
- up(&nftl->mutex);
- res = 0;
- goto repeat;
- }
- repeat:
- DEBUG(MTD_DEBUG_LEVEL3, "end_request(%d)\n", res);
- spin_lock_irq(&io_request_lock);
- end_request(res);
+ return -ENOTTY;
}
}
-static int nftl_open(struct inode *ip, struct file *fp)
-{
- int nftlnum = MINOR(ip->i_rdev) >> NFTL_PARTN_BITS;
- struct NFTLrecord *thisNFTL;
- thisNFTL = NFTLs[nftlnum];
-
- DEBUG(MTD_DEBUG_LEVEL2,"NFTL_open\n");
-
-#ifdef CONFIG_KMOD
- if (!thisNFTL && nftlnum == 0) {
- request_module("docprobe");
- thisNFTL = NFTLs[nftlnum];
- }
-#endif
- if (!thisNFTL) {
- DEBUG(MTD_DEBUG_LEVEL2,"ENODEV: thisNFTL = %d, minor = %d, ip = %p, fp = %p\n",
- nftlnum, ip->i_rdev, ip, fp);
- return -ENODEV;
- }
-
-#ifndef CONFIG_NFTL_RW
- if (fp->f_mode & FMODE_WRITE)
- return -EROFS;
-#endif /* !CONFIG_NFTL_RW */
-
- thisNFTL->usecount++;
- BLK_INC_USE_COUNT;
- if (!get_mtd_device(thisNFTL->mtd, -1)) {
- BLK_DEC_USE_COUNT;
- return -ENXIO;
- }
-
- return 0;
-}
-
-static int nftl_release(struct inode *inode, struct file *fp)
-{
- struct NFTLrecord *thisNFTL;
-
- thisNFTL = NFTLs[MINOR(inode->i_rdev) / 16];
-
- DEBUG(MTD_DEBUG_LEVEL2, "NFTL_release\n");
-
- if (thisNFTL->mtd->sync)
- thisNFTL->mtd->sync(thisNFTL->mtd);
- thisNFTL->usecount--;
- BLK_DEC_USE_COUNT;
-
- put_mtd_device(thisNFTL->mtd);
-
- return 0;
-}
-#if LINUX_VERSION_CODE < 0x20326
-static struct file_operations nftl_fops = {
- read: block_read,
- write: block_write,
- ioctl: nftl_ioctl,
- open: nftl_open,
- release: nftl_release,
- fsync: block_fsync,
-};
-#else
-static struct block_device_operations nftl_fops =
-{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,14)
- owner: THIS_MODULE,
-#endif
- open: nftl_open,
- release: nftl_release,
- ioctl: nftl_ioctl
-};
-#endif
-
-
/****************************************************************************
*
@@ -1048,49 +730,31 @@
*
****************************************************************************/
-static struct mtd_notifier nftl_notifier = {
- .add = NFTL_notify_add,
- .remove = NFTL_notify_remove
+
+struct mtd_blktrans_ops nftl_tr = {
+ .name = "nftl",
+ .major = NFTL_MAJOR,
+ .part_bits = NFTL_PARTN_BITS,
+ .ioctl = nftl_ioctl,
+ .readsect = nftl_readblock,
+ .writesect = nftl_writeblock,
+ .add_mtd = nftl_add_mtd,
+ .remove_dev = nftl_remove_dev,
+ .owner = THIS_MODULE,
};
extern char nftlmountrev[];
int __init init_nftl(void)
{
- int i;
-
-#ifdef PRERELEASE
printk(KERN_INFO "NFTL driver: nftlcore.c $Revision$, nftlmount.c %s\n", nftlmountrev);
-#endif
-
- if (register_blkdev(MAJOR_NR, "nftl", &nftl_fops)){
- printk("unable to register NFTL block device on major %d\n", MAJOR_NR);
- return -EBUSY;
- } else {
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), &nftl_request);
- /* set block size to 1kB each */
- for (i = 0; i < 256; i++) {
- nftl_blocksizes[i] = 1024;
- }
- blksize_size[MAJOR_NR] = nftl_blocksizes;
-
- add_gendisk(&nftl_gendisk);
- }
-
- register_mtd_user(&nftl_notifier);
-
- return 0;
+ return register_mtd_blktrans(&nftl_tr);
}
static void __exit cleanup_nftl(void)
{
- unregister_mtd_user(&nftl_notifier);
- unregister_blkdev(MAJOR_NR, "nftl");
-
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
-
- del_gendisk(&nftl_gendisk);
+ deregister_mtd_blktrans(&nftl_tr);
}
module_init(init_nftl);
More information about the linux-mtd-cvs
mailing list