diff options
author | Antonino A. Daplas <adaplas@gmail.com> | 2007-05-08 03:39:03 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-08 14:15:30 -0400 |
commit | 09aaf268eb1d22eee690d26a913f660e2081597f (patch) | |
tree | 9179447608d1c7ee23af266d2bae2eef6d05a1c9 /drivers/video | |
parent | 3f9b0880e4a96b02bc0131451f2f6231cd90bd94 (diff) |
fbdev: add fb_read/fb_write functions for framebuffers in system RAM
The functions fb_read() and fb_write in fbmem.c assume that the framebuffer
is in IO memory. However, we have 3 drivers (hecubafb, arcfb, and vfb)
where the framebuffer is allocated from system RAM (via vmalloc). Using
__raw_read/__raw_write (fb_readl/fb_writel) for these drivers is
illegal, especially in other platforms.
Create file read and write methods for these types of drivers. These are
named fb_sys_read() and fb_sys_write().
Signed-off-by: Antonino Daplas <adaplas@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/Kconfig | 5 | ||||
-rw-r--r-- | drivers/video/Makefile | 1 | ||||
-rw-r--r-- | drivers/video/fb_sys_fops.c | 104 |
3 files changed, 110 insertions, 0 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 6d32726e8751..85d0e8707ee3 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
@@ -122,6 +122,11 @@ config FB_SYS_IMAGEBLIT | |||
122 | blitting. This is used by drivers that don't provide their own | 122 | blitting. This is used by drivers that don't provide their own |
123 | (accelerated) version and the framebuffer is in system RAM. | 123 | (accelerated) version and the framebuffer is in system RAM. |
124 | 124 | ||
125 | config FB_SYS_FOPS | ||
126 | tristate | ||
127 | depends on FB | ||
128 | default n | ||
129 | |||
125 | config FB_DEFERRED_IO | 130 | config FB_DEFERRED_IO |
126 | bool | 131 | bool |
127 | depends on FB | 132 | depends on FB |
diff --git a/drivers/video/Makefile b/drivers/video/Makefile index fa025e786848..6c7b26e81fc2 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile | |||
@@ -21,6 +21,7 @@ obj-$(CONFIG_FB_CFB_IMAGEBLIT) += cfbimgblt.o | |||
21 | obj-$(CONFIG_FB_SYS_FILLRECT) += sysfillrect.o | 21 | obj-$(CONFIG_FB_SYS_FILLRECT) += sysfillrect.o |
22 | obj-$(CONFIG_FB_SYS_COPYAREA) += syscopyarea.o | 22 | obj-$(CONFIG_FB_SYS_COPYAREA) += syscopyarea.o |
23 | obj-$(CONFIG_FB_SYS_IMAGEBLIT) += sysimgblt.o | 23 | obj-$(CONFIG_FB_SYS_IMAGEBLIT) += sysimgblt.o |
24 | obj-$(CONFIG_FB_SYS_FOPS) += fb_sys_fops.o | ||
24 | obj-$(CONFIG_FB_SVGALIB) += svgalib.o | 25 | obj-$(CONFIG_FB_SVGALIB) += svgalib.o |
25 | obj-$(CONFIG_FB_MACMODES) += macmodes.o | 26 | obj-$(CONFIG_FB_MACMODES) += macmodes.o |
26 | obj-$(CONFIG_FB_DDC) += fb_ddc.o | 27 | obj-$(CONFIG_FB_DDC) += fb_ddc.o |
diff --git a/drivers/video/fb_sys_fops.c b/drivers/video/fb_sys_fops.c new file mode 100644 index 000000000000..cf2538d669cd --- /dev/null +++ b/drivers/video/fb_sys_fops.c | |||
@@ -0,0 +1,104 @@ | |||
1 | /* | ||
2 | * linux/drivers/video/fb_sys_read.c - Generic file operations where | ||
3 | * framebuffer is in system RAM | ||
4 | * | ||
5 | * Copyright (C) 2007 Antonino Daplas <adaplas@pol.net> | ||
6 | * | ||
7 | * This file is subject to the terms and conditions of the GNU General Public | ||
8 | * License. See the file COPYING in the main directory of this archive | ||
9 | * for more details. | ||
10 | * | ||
11 | */ | ||
12 | #include <linux/fb.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <asm/uaccess.h> | ||
15 | |||
16 | ssize_t fb_sys_read(struct fb_info *info, char __user *buf, size_t count, | ||
17 | loff_t *ppos) | ||
18 | { | ||
19 | unsigned long p = *ppos; | ||
20 | void *src; | ||
21 | int err = 0; | ||
22 | unsigned long total_size; | ||
23 | |||
24 | if (info->state != FBINFO_STATE_RUNNING) | ||
25 | return -EPERM; | ||
26 | |||
27 | total_size = info->screen_size; | ||
28 | |||
29 | if (total_size == 0) | ||
30 | total_size = info->fix.smem_len; | ||
31 | |||
32 | if (p >= total_size) | ||
33 | return 0; | ||
34 | |||
35 | if (count >= total_size) | ||
36 | count = total_size; | ||
37 | |||
38 | if (count + p > total_size) | ||
39 | count = total_size - p; | ||
40 | |||
41 | src = (void __force *)(info->screen_base + p); | ||
42 | |||
43 | if (info->fbops->fb_sync) | ||
44 | info->fbops->fb_sync(info); | ||
45 | |||
46 | if (copy_to_user(buf, src, count)) | ||
47 | err = -EFAULT; | ||
48 | |||
49 | if (!err) | ||
50 | *ppos += count; | ||
51 | |||
52 | return (err) ? err : count; | ||
53 | } | ||
54 | EXPORT_SYMBOL_GPL(fb_sys_read); | ||
55 | |||
56 | ssize_t fb_sys_write(struct fb_info *info, const char __user *buf, | ||
57 | size_t count, loff_t *ppos) | ||
58 | { | ||
59 | unsigned long p = *ppos; | ||
60 | void *dst; | ||
61 | int err = 0; | ||
62 | unsigned long total_size; | ||
63 | |||
64 | if (info->state != FBINFO_STATE_RUNNING) | ||
65 | return -EPERM; | ||
66 | |||
67 | total_size = info->screen_size; | ||
68 | |||
69 | if (total_size == 0) | ||
70 | total_size = info->fix.smem_len; | ||
71 | |||
72 | if (p > total_size) | ||
73 | return -EFBIG; | ||
74 | |||
75 | if (count > total_size) { | ||
76 | err = -EFBIG; | ||
77 | count = total_size; | ||
78 | } | ||
79 | |||
80 | if (count + p > total_size) { | ||
81 | if (!err) | ||
82 | err = -ENOSPC; | ||
83 | |||
84 | count = total_size - p; | ||
85 | } | ||
86 | |||
87 | dst = (void __force *) (info->screen_base + p); | ||
88 | |||
89 | if (info->fbops->fb_sync) | ||
90 | info->fbops->fb_sync(info); | ||
91 | |||
92 | if (copy_from_user(dst, buf, count)) | ||
93 | err = -EFAULT; | ||
94 | |||
95 | if (!err) | ||
96 | *ppos += count; | ||
97 | |||
98 | return (err) ? err : count; | ||
99 | } | ||
100 | EXPORT_SYMBOL_GPL(fb_sys_write); | ||
101 | |||
102 | MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>"); | ||
103 | MODULE_DESCRIPTION("Generic file read (fb in system RAM)"); | ||
104 | MODULE_LICENSE("GPL"); | ||