Sort out Linux kernel building with new driver model.
authorCharles Manning <cdhmanning@gmail.com>
Wed, 7 Nov 2012 01:15:20 +0000 (14:15 +1300)
committerCharles Manning <cdhmanning@gmail.com>
Wed, 7 Nov 2012 01:15:20 +0000 (14:15 +1300)
TODO yaffs_mtdif_single is just a copy of yaffs_mtdif_multi.

Signed-off-by: Charles Manning <cdhmanning@gmail.com>
Makefile.kernel
patch-ker.sh
yaffs_mtdif_single.c [new file with mode: 0644]

index 6a8729c..f9a9fb1 100644 (file)
@@ -6,8 +6,8 @@ obj-$(CONFIG_YAFFS_FS) += yaffs.o
 
 yaffs-y := yaffs_ecc.o yaffs_vfs.o yaffs_guts.o yaffs_checkptrw.o
 yaffs-y += yaffs_packedtags1.o yaffs_packedtags2.o yaffs_nand.o
-yaffs-y += yaffs_tagscompat.o
-yaffs-y += yaffs_mtdif.o yaffs_mtdif1.o yaffs_mtdif2.o
+yaffs-y += yaffs_tagscompat.o yaffs_tagsmarshall.o
+yaffs-y += yaffs_mtdif.o
 yaffs-y += yaffs_nameval.o yaffs_attribs.o
 yaffs-y += yaffs_allocator.o
 yaffs-y += yaffs_yaffs1.o
index ed54d53..3da6925 100755 (executable)
@@ -54,14 +54,12 @@ fi
 
 if [ $MULTIORSINGLE = m ]; then
    VFS_CODE="yaffs_vfs_multi.c"
-   MTD1_CODE="yaffs_mtdif1_multi.c"
-   MTD2_CODE="yaffs_mtdif2_multi.c"
+   MTD_CODE="yaffs_mtdif_multi.c"
    YPORTENV="yportenv_multi.h"
    KCONFIG_SRC="Kconfig_multi"
 elif [ $MULTIORSINGLE = s ]; then
    VFS_CODE="yaffs_vfs_single.c"
-   MTD1_CODE="yaffs_mtdif1_single.c"
-   MTD2_CODE="yaffs_mtdif2_single.c"
+   MTD_CODE="yaffs_mtdif_single.c"
    YPORTENV="yportenv_single.h"
    KCONFIG_SRC="Kconfig_single"
 
@@ -149,11 +147,10 @@ else
    $CPY  $PWD/Makefile.kernel $LINUXDIR/fs/yaffs2/Makefile
    $CPY $PWD/$KCONFIG_SRC $LINUXDIR/fs/yaffs2/Kconfig
    $CPY $PWD/*.c $PWD/*.h  $LINUXDIR/fs/yaffs2
-   rm $LINUXDIR/fs/yaffs2/yaffs_vfs*.c $LINUXDIR/fs/yaffs2/yaffs_mtdif[12]*.c
+   rm $LINUXDIR/fs/yaffs2/yaffs_vfs*.c $LINUXDIR/fs/yaffs2/yaffs_mtdif*.c
    rm $LINUXDIR/fs/yaffs2/yportenv*.h
    rm $LINUXDIR/fs/yaffs2/moduleconfig.h
    $CPY $PWD/$VFS_CODE $LINUXDIR/fs/yaffs2/yaffs_vfs.c
-   $CPY $PWD/$MTD1_CODE $LINUXDIR/fs/yaffs2/yaffs_mtdif1.c
-   $CPY $PWD/$MTD2_CODE $LINUXDIR/fs/yaffs2/yaffs_mtdif2.c
+   $CPY $PWD/$MTD_CODE $LINUXDIR/fs/yaffs2/yaffs_mtdif.c
    $CPY $PWD/$YPORTENV $LINUXDIR/fs/yaffs2/yportenv.h
 fi
diff --git a/yaffs_mtdif_single.c b/yaffs_mtdif_single.c
new file mode 100644 (file)
index 0000000..e61699d
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ *   for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "yportenv.h"
+
+#include "yaffs_mtdif.h"
+
+#include "linux/mtd/mtd.h"
+#include "linux/types.h"
+#include "linux/time.h"
+#include "linux/mtd/nand.h"
+#include "linux/kernel.h"
+#include "linux/version.h"
+#include "linux/types.h"
+
+#include "yaffs_trace.h"
+#include "yaffs_guts.h"
+#include "yaffs_linux.h"
+
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0))
+#define MTD_OPS_AUTO_OOB MTD_OOB_AUTO
+#endif
+
+
+int nandmtd_erase_block(struct yaffs_dev *dev, int block_no)
+{
+       struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
+       u32 addr =
+           ((loff_t) block_no) * dev->param.total_bytes_per_chunk *
+           dev->param.chunks_per_block;
+       struct erase_info ei;
+       int retval = 0;
+
+       ei.mtd = mtd;
+       ei.addr = addr;
+       ei.len = dev->param.total_bytes_per_chunk * dev->param.chunks_per_block;
+       ei.time = 1000;
+       ei.retries = 2;
+       ei.callback = NULL;
+       ei.priv = (u_long) dev;
+
+       retval = mtd->erase(mtd, &ei);
+
+       if (retval == 0)
+               return YAFFS_OK;
+
+       return YAFFS_FAIL;
+}
+
+
+static         int yaffs_mtd_write(struct yaffs_dev *dev, int nand_chunk,
+                                  const u8 *data, int data_len,
+                                  const u8 *oob, int oob_len)
+{
+       struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
+       loff_t addr;
+       struct mtd_oob_ops ops;
+       int retval;
+
+       addr = ((loff_t) nand_chunk) * dev->param.total_bytes_per_chunk;
+       memset(&ops, 0, sizeof(ops));
+       ops.mode = MTD_OPS_AUTO_OOB;
+       ops.len = (data) ? data_len : 0;
+       ops.ooblen = oob_len;
+       ops.datbuf = (u8 *)data;
+       ops.oobbuf = (u8 *)oob;
+
+       retval = mtd->write_oob(mtd, addr, &ops);
+       if (retval) {
+               yaffs_trace(YAFFS_TRACE_MTD,
+                       "write_oob failed, chunk %d, mtd error %d",
+                       nand_chunk, retval);
+       }
+       return retval ? YAFFS_FAIL : YAFFS_OK;
+}
+
+static int yaffs_mtd_read(struct yaffs_dev *dev, int nand_chunk,
+                                  u8 *data, int data_len,
+                                  u8 *oob, int oob_len,
+                                  enum yaffs_ecc_result *ecc_result)
+{
+       struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
+       loff_t addr;
+       struct mtd_oob_ops ops;
+       int retval;
+
+       addr = ((loff_t) nand_chunk) * dev->data_bytes_per_chunk;
+       memset(&ops, 0, sizeof(ops));
+       ops.mode = MTD_OPS_AUTO_OOB;
+       ops.len = (data) ? data_len : 0;
+       ops.ooblen = oob_len;
+       ops.datbuf = data;
+       ops.oobbuf = oob;
+
+#if (MTD_VERSION_CODE < MTD_VERSION(2, 6, 20))
+       /* In MTD 2.6.18 to 2.6.19 nand_base.c:nand_do_read_oob() has a bug;
+        * help it out with ops.len = ops.ooblen when ops.datbuf == NULL.
+        */
+       ops.len = (ops.datbuf) ? ops.len : ops.ooblen;
+#endif
+       /* Read page and oob using MTD.
+        * Check status and determine ECC result.
+        */
+       retval = mtd->read_oob(mtd, addr, &ops);
+       if (retval)
+               yaffs_trace(YAFFS_TRACE_MTD,
+                       "read_oob failed, chunk %d, mtd error %d",
+                       nand_chunk, retval);
+
+       switch (retval) {
+       case 0:
+               /* no error */
+               if(ecc_result)
+                       *ecc_result = YAFFS_ECC_RESULT_NO_ERROR;
+               break;
+
+       case -EUCLEAN:
+               /* MTD's ECC fixed the data */
+               if(ecc_result)
+                       *ecc_result = YAFFS_ECC_RESULT_FIXED;
+               dev->n_ecc_fixed++;
+               break;
+
+       case -EBADMSG:
+       default:
+               /* MTD's ECC could not fix the data */
+               dev->n_ecc_unfixed++;
+               if(ecc_result)
+                       *ecc_result = YAFFS_ECC_RESULT_UNFIXED;
+               return YAFFS_FAIL;
+       }
+
+       return YAFFS_OK;
+}
+
+static         int yaffs_mtd_erase(struct yaffs_dev *dev, int block_no)
+{
+       struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
+
+       loff_t addr;
+       struct erase_info ei;
+       int retval = 0;
+       u32 block_size;
+
+       block_size = dev->param.total_bytes_per_chunk *
+                    dev->param.chunks_per_block;
+       addr = ((loff_t) block_no) * block_size;
+
+       ei.mtd = mtd;
+       ei.addr = addr;
+       ei.len = block_size;
+       ei.time = 1000;
+       ei.retries = 2;
+       ei.callback = NULL;
+       ei.priv = (u_long) dev;
+
+       retval = mtd->erase(mtd, &ei);
+
+       if (retval == 0)
+               return YAFFS_OK;
+
+       return YAFFS_FAIL;
+}
+
+static int yaffs_mtd_mark_bad(struct yaffs_dev *dev, int block_no)
+{
+       struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
+       int blocksize = dev->param.chunks_per_block * dev->data_bytes_per_chunk;
+       int retval;
+
+       yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, "marking block %d bad", block_no);
+
+       retval = mtd->block_markbad(mtd, (loff_t) blocksize * block_no);
+       return (retval) ? YAFFS_FAIL : YAFFS_OK;
+}
+
+static int yaffs_mtd_check_bad(struct yaffs_dev *dev, int block_no)
+{
+       struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
+       int blocksize = dev->param.chunks_per_block * dev->data_bytes_per_chunk;
+       int retval;
+
+       yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, "checking block %d bad", block_no);
+
+       retval = mtd->block_isbad(mtd, (loff_t) blocksize * block_no);
+       return (retval) ? YAFFS_FAIL : YAFFS_OK;
+}
+
+static int yaffs_mtd_initialise(struct yaffs_dev *dev)
+{
+       return YAFFS_OK;
+}
+
+static int yaffs_mtd_deinitialise(struct yaffs_dev *dev)
+{
+       return YAFFS_OK;
+}
+
+
+
+void yaffs_mtd_drv_install(struct yaffs_dev *dev)
+{
+       struct yaffs_driver *drv = &dev->drv;
+
+       drv->drv_write_chunk_fn = yaffs_mtd_write;
+       drv->drv_read_chunk_fn = yaffs_mtd_read;
+       drv->drv_erase_fn = yaffs_mtd_erase;
+       drv->drv_mark_bad_fn = yaffs_mtd_mark_bad;
+       drv->drv_check_bad_fn = yaffs_mtd_check_bad;
+       drv->drv_initialise_fn = yaffs_mtd_initialise;
+       drv->drv_deinitialise_fn = yaffs_mtd_deinitialise;
+}