[PATCH 4/5] libmtd: add support for 64-bit offsets, OOB
Kevin Cernekee
cernekee at gmail.com
Mon Jul 5 18:10:37 EDT 2010
Change mtd_erase() so that it attempts to use MEMERASE64 first, then falls
back to the old <2.6.31 MEMERASE if MEMERASE64 is unsupported.
Add mtd_read_oob(), mtd_write_oob() functions to wrap the OOB ioctls.
Similar ioctl fallback logic is used in these functions as well.
Signed-off-by: Kevin Cernekee <cernekee at gmail.com>
---
include/libmtd.h | 26 +++++++++++++++++++++
lib/libmtd.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 88 insertions(+), 3 deletions(-)
diff --git a/include/libmtd.h b/include/libmtd.h
index 0aea966..2241343 100644
--- a/include/libmtd.h
+++ b/include/libmtd.h
@@ -149,6 +149,32 @@ int mtd_get_dev_info1(libmtd_t desc, int mtd_num, struct mtd_dev_info *mtd);
int mtd_erase(const struct mtd_dev_info *mtd, int fd, int eb);
/**
+ * mtd_read_oob - read OOB bytes
+ * @fd: MTD device node file descriptor
+ * @start: page-aligned start address
+ * @length: number of OOB bytes to read
+ * @data: read buffer
+ *
+ * This function reads @length OOB bytes starting from address @start on
+ * MTD device described by @fd. Returns %0 in case of success and %-1 in
+ * case of failure.
+ */
+int mtd_read_oob(int fd, uint64_t start, uint64_t length, void *data);
+
+/**
+ * mtd_write_oob - write OOB bytes
+ * @fd: MTD device node file descriptor
+ * @start: page-aligned start address
+ * @length: number of OOB bytes to write
+ * @data: write buffer
+ *
+ * This function writes @length OOB bytes starting from address @start on
+ * MTD device described by @fd. Returns %0 in case of success and %-1 in
+ * case of failure.
+ */
+int mtd_write_oob(int fd, uint64_t start, uint64_t length, void *data);
+
+/**
* mtd_torture - torture an eraseblock.
* @mtd: MTD device description object
* @fd: MTD device node file descriptor
diff --git a/lib/libmtd.c b/lib/libmtd.c
index 3ff031c..368493b 100644
--- a/lib/libmtd.c
+++ b/lib/libmtd.c
@@ -32,6 +32,7 @@
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <mtd/mtd-user.h>
+#include <mtd/mtd-abi.h>
#include <libmtd.h>
#include "libmtd_int.h"
@@ -791,11 +792,69 @@ int mtd_get_dev_info(libmtd_t desc, const char *node, struct mtd_dev_info *mtd)
int mtd_erase(const struct mtd_dev_info *mtd, int fd, int eb)
{
- struct erase_info_user ei;
+ int ret;
+ struct erase_info_user64 ei;
- ei.start = eb * mtd->eb_size;;
+ ei.start = (__u64)eb * mtd->eb_size;
ei.length = mtd->eb_size;
- return ioctl(fd, MEMERASE, &ei);
+ ret = ioctl(fd, MEMERASE64, &ei);
+
+ if (ret < 0 && errno == ENOTTY) {
+ struct erase_info_user ei_old;
+
+ ei_old.start = (__u32)ei.start;
+ ei_old.length = (__u32)ei.length;
+
+ if (ei_old.start != ei.start) {
+ errno = EOVERFLOW;
+ return -1;
+ }
+
+ ret = ioctl(fd, MEMERASE, &ei_old);
+ }
+
+ return ret;
+}
+
+static int mtd_oob_op(int cmd, int cmd_old, int fd, uint64_t start,
+ uint64_t length, void *data)
+{
+ int ret;
+ struct mtd_oob_buf64 oob;
+
+ oob.start = start;
+ oob.length = length;
+ oob.usr_ptr = (__u64)(unsigned long)data;
+
+ ret = ioctl(fd, cmd, &oob);
+
+ if (ret < 0 && errno == ENOTTY) {
+ struct mtd_oob_buf oob_old;
+
+ oob_old.start = (__u32)oob.start;
+ oob_old.length = (__u32)oob.length;
+ oob_old.ptr = data;
+
+ if (oob_old.start != oob.start ||
+ oob_old.length != oob.length) {
+ errno = EOVERFLOW;
+ return -1;
+ }
+
+ ret = ioctl(fd, cmd_old, &oob_old);
+ }
+
+ return ret;
+}
+
+int mtd_read_oob(int fd, uint64_t start, uint64_t length, void *data)
+{
+ return mtd_oob_op(MEMREADOOB64, MEMREADOOB, fd, start, length, data);
+}
+
+int mtd_write_oob(int fd, uint64_t start, uint64_t length, void *data)
+{
+ return mtd_oob_op(MEMWRITEOOB64, MEMWRITEOOB, fd, start, length, data);
}
/* Patterns to write to a physical eraseblock when torturing it */
--
1.6.5
More information about the linux-mtd
mailing list