diff options
author | Oliver Schinagl <oliver@schinagl.nl> | 2011-02-26 12:16:43 (GMT) |
---|---|---|
committer | Oliver Schinagl <oliver@schinagl.nl> | 2011-02-26 12:16:43 (GMT) |
commit | edb45850f53478c7779484105c30f8df0a3a3782 (patch) | |
tree | 26e758b463e03475be4d214aeb17c6517b01a83e /linux-2.4.x/drivers/mtd/mtdchar.c | |
parent | ba6dc76a789f33fc999bbd24fe8af5b856f90085 (diff) | |
download | openipcam-edb45850f53478c7779484105c30f8df0a3a3782.zip openipcam-edb45850f53478c7779484105c30f8df0a3a3782.tar.gz openipcam-edb45850f53478c7779484105c30f8df0a3a3782.tar.bz2 |
2.4.20-uc0 uClinux patch added
Diffstat (limited to 'linux-2.4.x/drivers/mtd/mtdchar.c')
-rw-r--r-- | linux-2.4.x/drivers/mtd/mtdchar.c | 78 |
1 files changed, 77 insertions, 1 deletions
diff --git a/linux-2.4.x/drivers/mtd/mtdchar.c b/linux-2.4.x/drivers/mtd/mtdchar.c index f602eb2..1780055 100644 --- a/linux-2.4.x/drivers/mtd/mtdchar.c +++ b/linux-2.4.x/drivers/mtd/mtdchar.c @@ -434,9 +434,83 @@ static int mtd_ioctl(struct inode *inode, struct file *file, break; } + case MEMWRITEDATA: + { + struct mtd_oob_buf buf; + void *databuf; + ssize_t retlen; + + if (copy_from_user(&buf, (struct mtd_oob_buf *)arg, sizeof(struct mtd_oob_buf))) + return -EFAULT; + + if (buf.length > 0x4096) + return -EINVAL; + + if (!mtd->write_ecc) + ret = -EOPNOTSUPP; + else + ret = verify_area(VERIFY_READ, (char *)buf.ptr, buf.length); + + if (ret) + return ret; + + databuf = kmalloc(buf.length, GFP_KERNEL); + if (!databuf) + return -ENOMEM; + + if (copy_from_user(databuf, buf.ptr, buf.length)) { + kfree(databuf); + return -EFAULT; + } + + ret = (mtd->write_ecc)(mtd, buf.start, buf.length, &retlen, databuf, NULL); + + if (copy_to_user((void *)arg + sizeof(u_int32_t), &retlen, sizeof(u_int32_t))) + ret = -EFAULT; + + kfree(databuf); + break; + + } + + case MEMREADDATA: + { + struct mtd_oob_buf buf; + void *databuf; + ssize_t retlen = 0; + + if (copy_from_user(&buf, (struct mtd_oob_buf *)arg, sizeof(struct mtd_oob_buf))) + return -EFAULT; + + if (buf.length > 0x4096) + return -EINVAL; + + if (!mtd->read_ecc) + ret = -EOPNOTSUPP; + else + ret = verify_area(VERIFY_WRITE, (char *)buf.ptr, buf.length); + + if (ret) + return ret; + + databuf = kmalloc(buf.length, GFP_KERNEL); + if (!databuf) + return -ENOMEM; + + ret = (mtd->read_ecc)(mtd, buf.start, buf.length, &retlen, databuf, NULL); + + if (copy_to_user((void *)arg + sizeof(u_int32_t), &retlen, sizeof(u_int32_t))) + ret = -EFAULT; + else if (retlen && copy_to_user(buf.ptr, databuf, retlen)) + ret = -EFAULT; + + kfree(databuf); + break; + } + default: - DEBUG(MTD_DEBUG_LEVEL0, "Invalid ioctl %x (MEMGETINFO = %x)\n", cmd, MEMGETINFO); + DEBUG(MTD_DEBUG_LEVEL0, "Invalid ioctl %x (MEMGETINFO = %lx)\n", cmd, MEMGETINFO); ret = -ENOTTY; } @@ -509,6 +583,8 @@ static int __init init_mtdchar(void) return -EAGAIN; } #endif + DEBUG(MTD_DEBUG_LEVEL3, + "init_mtdchar: allocated major number %d.\n", MTD_CHAR_MAJOR); return 0; } |