diff --git a/drivers/nand/nand.c b/drivers/nand/nand.c index b72cbb1..a058df2 100644 --- a/drivers/nand/nand.c +++ b/drivers/nand/nand.c @@ -29,6 +29,7 @@ #include #include #include +#include static ssize_t nand_read(struct cdev *cdev, void* buf, size_t count, ulong offset, ulong flags) { @@ -158,8 +159,41 @@ .erase = nand_erase, }; +static ssize_t nand_read_oob(struct cdev *cdev, void *buf, size_t count, ulong offset, ulong flags) +{ + struct mtd_info *info = cdev->priv; + struct nand_chip *chip = info->priv; + struct mtd_oob_ops ops; + int ret; + + if (count < info->oobsize) + return -EINVAL; + + ops.mode = MTD_OOB_RAW; + ops.ooboffs = 0; + ops.ooblen = info->oobsize; + ops.oobbuf = buf; + ops.datbuf = NULL; + ops.len = info->oobsize; + + offset /= info->oobsize; + ret = info->read_oob(info, offset << chip->page_shift, &ops); + if (ret) + return ret; + + return info->oobsize; +} + +static struct file_operations nand_ops_oob = { + .read = nand_read_oob, + .ioctl = nand_ioctl, + .lseek = dev_lseek_default, +}; + int add_mtd_device(struct mtd_info *mtd) { + struct nand_chip *chip = mtd->priv; + strcpy(mtd->class_dev.name, "nand"); register_device(&mtd->class_dev); @@ -176,6 +210,13 @@ devfs_create(&mtd->cdev); + mtd->cdev_oob.ops = &nand_ops_oob; + mtd->cdev_oob.size = (mtd->size >> chip->page_shift) * mtd->oobsize; + mtd->cdev_oob.name = asprintf("nand_oob%d", mtd->class_dev.id); + mtd->cdev_oob.priv = mtd; + mtd->cdev_oob.dev = &mtd->class_dev; + devfs_create(&mtd->cdev_oob); + return 0; } diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index b574778..42bfcab 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -203,6 +203,7 @@ struct device_d class_dev; struct device_d *dev; struct cdev cdev; + struct cdev cdev_oob; struct param_d param_size; char *size_str;