diff options
Diffstat (limited to 'drivers/mtd/mtdchar.c')
-rw-r--r-- | drivers/mtd/mtdchar.c | 48 |
1 files changed, 27 insertions, 21 deletions
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index 6ea2d8058a4a..548b89204aa2 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: mtdchar.c,v 1.67 2005/02/08 17:45:51 nico Exp $ | 2 | * $Id: mtdchar.c,v 1.68 2005/02/08 19:12:50 nico Exp $ |
3 | * | 3 | * |
4 | * Character-device access to raw MTD devices. | 4 | * Character-device access to raw MTD devices. |
5 | * | 5 | * |
@@ -59,15 +59,25 @@ static inline void mtdchar_devfs_exit(void) | |||
59 | #define mtdchar_devfs_exit() do { } while(0) | 59 | #define mtdchar_devfs_exit() do { } while(0) |
60 | #endif | 60 | #endif |
61 | 61 | ||
62 | /* | ||
63 | * We use file->private_data to store a pointer to the MTDdevice. | ||
64 | * Since alighment is at least 32 bits, we have 2 bits free for OTP | ||
65 | * modes as well. | ||
66 | */ | ||
67 | |||
68 | #define TO_MTD(file) (struct mtd_info *)((long)((file)->private_data) & ~3L) | ||
62 | 69 | ||
63 | /* Well... let's abuse the unused bits in file->f_mode for those */ | 70 | #define MTD_MODE_OTP_FACT 1 |
64 | #define MTD_MODE_OTP_FACT 0x1000 | 71 | #define MTD_MODE_OTP_USER 2 |
65 | #define MTD_MODE_OTP_USER 0x2000 | 72 | #define MTD_MODE(file) ((long)((file)->private_data) & 3) |
66 | #define MTD_MODE_MASK 0xf000 | 73 | |
74 | #define SET_MTD_MODE(file, mode) \ | ||
75 | do { long __p = (long)((file)->private_data); \ | ||
76 | (file)->private_data = (void *)((__p & ~3L) | mode); } while (0) | ||
67 | 77 | ||
68 | static loff_t mtd_lseek (struct file *file, loff_t offset, int orig) | 78 | static loff_t mtd_lseek (struct file *file, loff_t offset, int orig) |
69 | { | 79 | { |
70 | struct mtd_info *mtd = file->private_data; | 80 | struct mtd_info *mtd = TO_MTD(file); |
71 | 81 | ||
72 | switch (orig) { | 82 | switch (orig) { |
73 | case 0: | 83 | case 0: |
@@ -111,10 +121,6 @@ static int mtd_open(struct inode *inode, struct file *file) | |||
111 | if ((file->f_mode & 2) && (minor & 1)) | 121 | if ((file->f_mode & 2) && (minor & 1)) |
112 | return -EACCES; | 122 | return -EACCES; |
113 | 123 | ||
114 | /* make sure the locally abused bits are initialy clear */ | ||
115 | if (file->f_mode & MTD_MODE_MASK) | ||
116 | return -EWOULDBLOCK; | ||
117 | |||
118 | mtd = get_mtd_device(NULL, devnum); | 124 | mtd = get_mtd_device(NULL, devnum); |
119 | 125 | ||
120 | if (!mtd) | 126 | if (!mtd) |
@@ -144,7 +150,7 @@ static int mtd_close(struct inode *inode, struct file *file) | |||
144 | 150 | ||
145 | DEBUG(MTD_DEBUG_LEVEL0, "MTD_close\n"); | 151 | DEBUG(MTD_DEBUG_LEVEL0, "MTD_close\n"); |
146 | 152 | ||
147 | mtd = file->private_data; | 153 | mtd = TO_MTD(file); |
148 | 154 | ||
149 | if (mtd->sync) | 155 | if (mtd->sync) |
150 | mtd->sync(mtd); | 156 | mtd->sync(mtd); |
@@ -161,7 +167,7 @@ static int mtd_close(struct inode *inode, struct file *file) | |||
161 | 167 | ||
162 | static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t *ppos) | 168 | static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t *ppos) |
163 | { | 169 | { |
164 | struct mtd_info *mtd = file->private_data; | 170 | struct mtd_info *mtd = TO_MTD(file); |
165 | size_t retlen=0; | 171 | size_t retlen=0; |
166 | size_t total_retlen=0; | 172 | size_t total_retlen=0; |
167 | int ret=0; | 173 | int ret=0; |
@@ -188,7 +194,7 @@ static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t | |||
188 | if (!kbuf) | 194 | if (!kbuf) |
189 | return -ENOMEM; | 195 | return -ENOMEM; |
190 | 196 | ||
191 | switch (file->f_mode & MTD_MODE_MASK) { | 197 | switch (MTD_MODE(file)) { |
192 | case MTD_MODE_OTP_FACT: | 198 | case MTD_MODE_OTP_FACT: |
193 | ret = mtd->read_fact_prot_reg(mtd, *ppos, len, &retlen, kbuf); | 199 | ret = mtd->read_fact_prot_reg(mtd, *ppos, len, &retlen, kbuf); |
194 | break; | 200 | break; |
@@ -231,7 +237,7 @@ static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t | |||
231 | 237 | ||
232 | static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count,loff_t *ppos) | 238 | static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count,loff_t *ppos) |
233 | { | 239 | { |
234 | struct mtd_info *mtd = file->private_data; | 240 | struct mtd_info *mtd = TO_MTD(file); |
235 | char *kbuf; | 241 | char *kbuf; |
236 | size_t retlen; | 242 | size_t retlen; |
237 | size_t total_retlen=0; | 243 | size_t total_retlen=0; |
@@ -266,7 +272,7 @@ static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count | |||
266 | return -EFAULT; | 272 | return -EFAULT; |
267 | } | 273 | } |
268 | 274 | ||
269 | switch (file->f_mode & MTD_MODE_MASK) { | 275 | switch (MTD_MODE(file)) { |
270 | case MTD_MODE_OTP_FACT: | 276 | case MTD_MODE_OTP_FACT: |
271 | ret = -EROFS; | 277 | ret = -EROFS; |
272 | break; | 278 | break; |
@@ -310,7 +316,7 @@ static void mtdchar_erase_callback (struct erase_info *instr) | |||
310 | static int mtd_ioctl(struct inode *inode, struct file *file, | 316 | static int mtd_ioctl(struct inode *inode, struct file *file, |
311 | u_int cmd, u_long arg) | 317 | u_int cmd, u_long arg) |
312 | { | 318 | { |
313 | struct mtd_info *mtd = file->private_data; | 319 | struct mtd_info *mtd = TO_MTD(file); |
314 | void __user *argp = (void __user *)arg; | 320 | void __user *argp = (void __user *)arg; |
315 | int ret = 0; | 321 | int ret = 0; |
316 | u_long size; | 322 | u_long size; |
@@ -558,19 +564,19 @@ static int mtd_ioctl(struct inode *inode, struct file *file, | |||
558 | int mode; | 564 | int mode; |
559 | if (copy_from_user(&mode, argp, sizeof(int))) | 565 | if (copy_from_user(&mode, argp, sizeof(int))) |
560 | return -EFAULT; | 566 | return -EFAULT; |
561 | file->f_mode &= ~MTD_MODE_MASK; | 567 | SET_MTD_MODE(file, 0); |
562 | switch (mode) { | 568 | switch (mode) { |
563 | case MTD_OTP_FACTORY: | 569 | case MTD_OTP_FACTORY: |
564 | if (!mtd->read_fact_prot_reg) | 570 | if (!mtd->read_fact_prot_reg) |
565 | ret = -EOPNOTSUPP; | 571 | ret = -EOPNOTSUPP; |
566 | else | 572 | else |
567 | file->f_mode |= MTD_MODE_OTP_FACT; | 573 | SET_MTD_MODE(file, MTD_MODE_OTP_FACT); |
568 | break; | 574 | break; |
569 | case MTD_OTP_USER: | 575 | case MTD_OTP_USER: |
570 | if (!mtd->read_fact_prot_reg) | 576 | if (!mtd->read_fact_prot_reg) |
571 | ret = -EOPNOTSUPP; | 577 | ret = -EOPNOTSUPP; |
572 | else | 578 | else |
573 | file->f_mode |= MTD_MODE_OTP_USER; | 579 | SET_MTD_MODE(file, MTD_MODE_OTP_USER); |
574 | break; | 580 | break; |
575 | default: | 581 | default: |
576 | ret = -EINVAL; | 582 | ret = -EINVAL; |
@@ -587,7 +593,7 @@ static int mtd_ioctl(struct inode *inode, struct file *file, | |||
587 | if (!buf) | 593 | if (!buf) |
588 | return -ENOMEM; | 594 | return -ENOMEM; |
589 | ret = -EOPNOTSUPP; | 595 | ret = -EOPNOTSUPP; |
590 | switch (file->f_mode & MTD_MODE_MASK) { | 596 | switch (MTD_MODE(file)) { |
591 | case MTD_MODE_OTP_FACT: | 597 | case MTD_MODE_OTP_FACT: |
592 | if (mtd->get_fact_prot_info) | 598 | if (mtd->get_fact_prot_info) |
593 | ret = mtd->get_fact_prot_info(mtd, buf, 4096); | 599 | ret = mtd->get_fact_prot_info(mtd, buf, 4096); |
@@ -614,7 +620,7 @@ static int mtd_ioctl(struct inode *inode, struct file *file, | |||
614 | { | 620 | { |
615 | struct otp_info info; | 621 | struct otp_info info; |
616 | 622 | ||
617 | if ((file->f_mode & MTD_MODE_MASK) != MTD_MODE_OTP_USER) | 623 | if (MTD_MODE(file) != MTD_MODE_OTP_USER) |
618 | return -EINVAL; | 624 | return -EINVAL; |
619 | if (copy_from_user(&info, argp, sizeof(info))) | 625 | if (copy_from_user(&info, argp, sizeof(info))) |
620 | return -EFAULT; | 626 | return -EFAULT; |