patch-2.4.0-test12 linux/drivers/mtd/mtdchar.c
Next file: linux/drivers/mtd/mtdcore.c
Previous file: linux/drivers/mtd/mtdblock.c
Back to the patch index
Back to the overall index
- Lines: 346
- Date:
Mon Dec 11 14:57:58 2000
- Orig file:
v2.4.0-test11/linux/drivers/mtd/mtdchar.c
- Orig date:
Fri Jul 14 14:51:53 2000
diff -u --recursive --new-file v2.4.0-test11/linux/drivers/mtd/mtdchar.c linux/drivers/mtd/mtdchar.c
@@ -1,5 +1,6 @@
/*
- * $Id: mtdchar.c,v 1.7 2000/06/30 15:54:19 dwmw2 Exp $
+ * Almost: $Id: mtdchar.c,v 1.21 2000/12/09 21:15:12 dwmw2 Exp $
+ * (With some of the compatibility for previous kernels taken out)
*
* Character-device access to raw MTD devices.
*
@@ -13,6 +14,20 @@
#include <linux/mtd/mtd.h>
#include <linux/malloc.h>
+#ifdef CONFIG_DEVFS_FS
+#include <linux/devfs_fs_kernel.h>
+static void mtd_notify_add(struct mtd_info* mtd);
+static void mtd_notify_remove(struct mtd_info* mtd);
+static struct mtd_notifier notifier = {
+ mtd_notify_add,
+ mtd_notify_remove,
+ NULL
+};
+static devfs_handle_t devfs_dir_handle = NULL;
+static devfs_handle_t devfs_rw_handle[MAX_MTD_DEVICES];
+static devfs_handle_t devfs_ro_handle[MAX_MTD_DEVICES];
+#endif
+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
static loff_t mtd_lseek (struct file *file, loff_t offset, int orig)
#else
@@ -22,11 +37,11 @@
struct mtd_info *mtd=(struct mtd_info *)file->private_data;
switch (orig) {
- case 0:
+ case 0:
/* SEEK_SET */
file->f_pos = offset;
break;
- case 1:
+ case 1:
/* SEEK_CUR */
file->f_pos += offset;
break;
@@ -34,11 +49,11 @@
/* SEEK_END */
file->f_pos =mtd->size + offset;
break;
- default:
+ default:
return -EINVAL;
}
- if (file->f_pos < 0)
+ if (file->f_pos < 0)
file->f_pos = 0;
else if (file->f_pos >= mtd->size)
file->f_pos = mtd->size - 1;
@@ -54,7 +69,7 @@
int devnum = minor >> 1;
struct mtd_info *mtd;
- DEBUG(0, "MTD_open\n");
+ DEBUG(MTD_DEBUG_LEVEL0, "MTD_open\n");
if (devnum >= MAX_MTD_DEVICES)
return -ENODEV;
@@ -86,7 +101,7 @@
{
struct mtd_info *mtd;
- DEBUG(0, "MTD_close\n");
+ DEBUG(MTD_DEBUG_LEVEL0, "MTD_close\n");
mtd = (struct mtd_info *)file->private_data;
@@ -115,7 +130,7 @@
int ret=0;
char *kbuf;
- DEBUG(0,"MTD_read\n");
+ DEBUG(MTD_DEBUG_LEVEL0,"MTD_read\n");
if (FILE_POS + count > mtd->size)
count = mtd->size - FILE_POS;
@@ -124,7 +139,7 @@
return 0;
/* FIXME: Use kiovec in 2.3 or 2.2+rawio, or at
- * least split the IO into smaller chunks.
+ * least split the IO into smaller chunks.
*/
kbuf = vmalloc(count);
@@ -157,7 +172,7 @@
size_t retlen;
int ret=0;
- DEBUG(0,"MTD_write\n");
+ DEBUG(MTD_DEBUG_LEVEL0,"MTD_write\n");
if (FILE_POS == mtd->size)
return -ENOSPC;
@@ -208,7 +223,7 @@
int ret = 0;
u_long size;
- DEBUG(0, "MTD_ioctl\n");
+ DEBUG(MTD_DEBUG_LEVEL0, "MTD_ioctl\n");
size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT;
if (cmd & IOC_IN) {
@@ -222,8 +237,9 @@
switch (cmd) {
case MEMGETINFO:
- copy_to_user((struct mtd_info *)arg, mtd,
- sizeof(struct mtd_info_user));
+ if (copy_to_user((struct mtd_info *)arg, mtd,
+ sizeof(struct mtd_info_user)))
+ return -EFAULT;
break;
case MEMERASE:
@@ -238,28 +254,23 @@
init_waitqueue_head(&waitq);
memset (erase,0,sizeof(struct erase_info));
- copy_from_user(&erase->addr, (u_long *)arg,
- 2 * sizeof(u_long));
+ if (copy_from_user(&erase->addr, (u_long *)arg,
+ 2 * sizeof(u_long))) {
+ kfree(erase);
+ return -EFAULT;
+ }
erase->mtd = mtd;
erase->callback = mtd_erase_callback;
erase->priv = (unsigned long)&waitq;
- /* FIXME: Allow INTERRUPTIBLE. Which means
- not having the wait_queue head on the stack
-
- Does it? Why? Who wrote this? Was it my alter
- ago - the intelligent one? Or was it the stupid
- one, and now I'm being clever I don't know what
- it was on about?
-
- dwmw2.
-
- It was the intelligent one. If the wq_head is
- on the stack, and we leave because we got
- interrupted, then the wq_head is no longer
- there when the callback routine tries to
- wake us up --> BOOM!.
-
+ /*
+ FIXME: Allow INTERRUPTIBLE. Which means
+ not having the wait_queue head on the stack.
+
+ If the wq_head is on the stack, and we
+ leave because we got interrupted, then the
+ wq_head is no longer there when the
+ callback routine tries to wake us up.
*/
current->state = TASK_UNINTERRUPTIBLE;
add_wait_queue(&waitq, &wait);
@@ -281,7 +292,8 @@
void *databuf;
ssize_t retlen;
- copy_from_user(&buf, (struct mtd_oob_buf *)arg, sizeof(struct mtd_oob_buf));
+ if (copy_from_user(&buf, (struct mtd_oob_buf *)arg, sizeof(struct mtd_oob_buf)))
+ return -EFAULT;
if (buf.length > 0x4096)
return -EINVAL;
@@ -298,11 +310,13 @@
if (!databuf)
return -ENOMEM;
- copy_from_user(databuf, buf.ptr, buf.length);
+ if (copy_from_user(databuf, buf.ptr, buf.length))
+ return -EFAULT;
ret = (mtd->write_oob)(mtd, buf.start, buf.length, &retlen, databuf);
- copy_to_user((void *)arg + sizeof(loff_t), &retlen, sizeof(ssize_t));
+ if (copy_to_user((void *)arg + sizeof(loff_t), &retlen, sizeof(ssize_t)))
+ ret = -EFAULT;
kfree(databuf);
break;
@@ -315,7 +329,8 @@
void *databuf;
ssize_t retlen;
- copy_from_user(&buf, (struct mtd_oob_buf *)arg, sizeof(struct mtd_oob_buf));
+ if (copy_from_user(&buf, (struct mtd_oob_buf *)arg, sizeof(struct mtd_oob_buf)))
+ return -EFAULT;
if (buf.length > 0x4096)
return -EINVAL;
@@ -334,19 +349,42 @@
ret = (mtd->read_oob)(mtd, buf.start, buf.length, &retlen, databuf);
- copy_to_user((void *)arg + sizeof(loff_t), &retlen, sizeof(ssize_t));
-
- if (retlen)
- copy_to_user(buf.ptr, databuf, retlen);
-
+ if (copy_to_user((void *)arg + sizeof(loff_t), &retlen, sizeof(ssize_t)))
+ ret = -EFAULT;
+ else if (retlen && copy_to_user(buf.ptr, databuf, retlen))
+ ret = -EFAULT;
+
kfree(databuf);
break;
}
-
-
-
-
+ case MEMLOCK:
+ {
+ unsigned long adrs[2];
+
+ if (copy_from_user(adrs ,(void *)arg, 2* sizeof(unsigned long)))
+ return -EFAULT;
+
+ if (!mtd->lock)
+ ret = -EOPNOTSUPP;
+ else
+ ret = mtd->lock(mtd, adrs[0], adrs[1]);
+ }
+
+ case MEMUNLOCK:
+ {
+ unsigned long adrs[2];
+
+ if (copy_from_user(adrs, (void *)arg, 2* sizeof(unsigned long)))
+ return -EFAULT;
+
+ if (!mtd->unlock)
+ ret = -EOPNOTSUPP;
+ else
+ ret = mtd->unlock(mtd, adrs[0], adrs[1]);
+ }
+
+
default:
printk("Invalid ioctl %x (MEMGETINFO = %x)\n",cmd, MEMGETINFO);
ret = -EINVAL;
@@ -366,31 +404,84 @@
};
-#if LINUX_VERSION_CODE < 0x20300
-#ifdef MODULE
+#ifdef CONFIG_DEVFS_FS
+/* Notification that a new device has been added. Create the devfs entry for
+ * it. */
+
+static void mtd_notify_add(struct mtd_info* mtd)
+{
+ char name[8];
+
+ if (!mtd)
+ return;
+
+ sprintf(name, "%d", mtd->index);
+ devfs_rw_handle[mtd->index] = devfs_register(devfs_dir_handle, name,
+ DEVFS_FL_DEFAULT, MTD_CHAR_MAJOR, mtd->index*2,
+ S_IFCHR | S_IRUGO | S_IWUGO,
+ &mtd_fops, NULL);
+
+ sprintf(name, "%dro", mtd->index);
+ devfs_ro_handle[mtd->index] = devfs_register(devfs_dir_handle, name,
+ DEVFS_FL_DEFAULT, MTD_CHAR_MAJOR, mtd->index*2+1,
+ S_IFCHR | S_IRUGO | S_IWUGO,
+ &mtd_fops, NULL);
+}
+
+static void mtd_notify_remove(struct mtd_info* mtd)
+{
+ if (!mtd)
+ return;
+
+ devfs_unregister(devfs_rw_handle[mtd->index]);
+ devfs_unregister(devfs_ro_handle[mtd->index]);
+}
+#endif
+
+#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE)
#define init_mtdchar init_module
#define cleanup_mtdchar cleanup_module
#endif
-#endif
mod_init_t init_mtdchar(void)
{
-
- if (register_chrdev(MTD_CHAR_MAJOR,"mtd",&mtd_fops)) {
+#ifdef CONFIG_DEVFS_FS
+ int i;
+ char name[8];
+ struct mtd_info* mtd;
+
+ if (devfs_register_chrdev(MTD_CHAR_MAJOR, "mtd", &mtd_fops))
+ {
+ printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n",
+ MTD_CHAR_MAJOR);
+ return -EAGAIN;
+ }
+
+ devfs_dir_handle = devfs_mk_dir(NULL, "mtd", NULL);
+
+ register_mtd_user(¬ifier);
+#else
+ if (register_chrdev(MTD_CHAR_MAJOR, "mtd", &mtd_fops))
+ {
printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n",
MTD_CHAR_MAJOR);
return -EAGAIN;
}
+#endif
return 0;
}
mod_exit_t cleanup_mtdchar(void)
{
- unregister_chrdev(MTD_CHAR_MAJOR,"mtd");
+#ifdef CONFIG_DEVFS_FS
+ unregister_mtd_user(¬ifier);
+ devfs_unregister(devfs_dir_handle);
+ devfs_unregister_chrdev(MTD_CHAR_MAJOR, "mtd");
+#else
+ unregister_chrdev(MTD_CHAR_MAJOR, "mtd");
+#endif
}
-#if LINUX_VERSION_CODE > 0x20300
module_init(init_mtdchar);
module_exit(cleanup_mtdchar);
-#endif
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)