summaryrefslogtreecommitdiffstats
path: root/linux-2.4.x/drivers/mtd/mtdchar.c
diff options
context:
space:
mode:
authorOliver Schinagl <oliver@schinagl.nl>2011-02-26 12:16:43 (GMT)
committerOliver Schinagl <oliver@schinagl.nl>2011-02-26 12:16:43 (GMT)
commitedb45850f53478c7779484105c30f8df0a3a3782 (patch)
tree26e758b463e03475be4d214aeb17c6517b01a83e /linux-2.4.x/drivers/mtd/mtdchar.c
parentba6dc76a789f33fc999bbd24fe8af5b856f90085 (diff)
downloadopenipcam-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.c78
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;
}