This source file includes following definitions.
- PROC_CONSOLE
- fb_read
- fb_write
- fb_ioctl
- fb_mmap
- fb_open
- fb_release
- register_framebuffer
- unregister_framebuffer
- fbmem_init
1
2
3
4
5
6
7
8
9
10
11 #include <linux/types.h>
12 #include <linux/errno.h>
13 #include <linux/sched.h>
14 #include <linux/kernel.h>
15 #include <linux/major.h>
16 #include <linux/malloc.h>
17 #include <linux/mman.h>
18 #include <linux/tty.h>
19
20 #include <asm/segment.h>
21 #include <asm/bootinfo.h>
22 #include <asm/page.h>
23 #include <asm/pgtable.h>
24
25 #include <linux/fb.h>
26
27 #define FB_MAJOR 29
28
29 #define FB_MODES_SHIFT 5
30 #define FB_NUM_MINORS 256
31 #define FB_MAX (FB_NUM_MINORS / (1 << FB_MODES_SHIFT))
32
33 #define GET_INODE(i) MKDEV(FB_MAJOR, (i) << FB_MODES_SHIFT)
34 #define GET_FB_IDX(node) (MINOR(node) >> FB_MODES_SHIFT)
35 #define GET_FB_VAR_IDX(node) (MINOR(node) & ((1 << FB_MODES_SHIFT)-1))
36
37 struct fb_ops *registered_fb[FB_MAX];
38 struct fb_var_screeninfo *registered_fb_var[FB_MAX];
39 int registered_fb_var_num[FB_MAX];
40 int fb_curr_open[FB_MAX];
41 int fb_open_count[FB_MAX];
42
43 static inline int PROC_CONSOLE(void)
44 {
45 if (!current->tty)
46 return fg_console;
47
48 if (current->tty->driver.type != TTY_DRIVER_TYPE_CONSOLE)
49
50 return fg_console;
51
52 if (MINOR(current->tty->device) < 1)
53 return fg_console;
54
55 return MINOR(current->tty->device) - 1;
56 }
57
58 static int
59 fb_read(struct inode *inode, struct file *file, char *buf, int count)
60 {
61 unsigned long p = file->f_pos;
62 struct fb_ops *fb = registered_fb[GET_FB_IDX(inode->i_rdev)];
63 struct fb_fix_screeninfo fix;
64 char *base_addr;
65 int copy_size;
66
67 if (! fb)
68 return -ENODEV;
69 if (count < 0)
70 return -EINVAL;
71
72 fb->fb_get_fix(&fix,PROC_CONSOLE());
73 base_addr=(char *) fix.smem_start;
74 copy_size=(count + p <= fix.smem_len ? count : fix.smem_len - p);
75 memcpy_tofs(buf, base_addr+p, copy_size);
76 file->f_pos += copy_size;
77 return copy_size;
78 }
79
80 static int
81 fb_write(struct inode *inode, struct file *file, const char *buf, int count)
82 {
83 unsigned long p = file->f_pos;
84 struct fb_ops *fb = registered_fb[GET_FB_IDX(inode->i_rdev)];
85 struct fb_fix_screeninfo fix;
86 char *base_addr;
87 int copy_size;
88
89 if (! fb)
90 return -ENODEV;
91 if (count < 0)
92 return -EINVAL;
93 fb->fb_get_fix(&fix, PROC_CONSOLE());
94 base_addr=(char *) fix.smem_start;
95 copy_size=(count + p <= fix.smem_len ? count : fix.smem_len - p);
96 memcpy_fromfs(base_addr+p, buf, copy_size);
97 file->f_pos += copy_size;
98 return copy_size;
99 }
100
101
102 static int
103 fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
104 unsigned long arg)
105 {
106 struct fb_ops *fb = registered_fb[GET_FB_IDX(inode->i_rdev)];
107 struct fb_cmap cmap;
108 struct fb_var_screeninfo var;
109 struct fb_fix_screeninfo fix;
110
111 int i,fbidx,vidx;
112
113 if (! fb)
114 return -ENODEV;
115 switch (cmd) {
116 case FBIOGET_VSCREENINFO:
117 i = verify_area(VERIFY_WRITE, (void *) arg,
118 sizeof(struct fb_var_screeninfo));
119 if (i) return i;
120 fbidx=GET_FB_IDX(inode->i_rdev);
121 vidx=GET_FB_VAR_IDX(inode->i_rdev);
122 if (! vidx)
123 i=fb->fb_get_var(&var, PROC_CONSOLE());
124 else
125 var=registered_fb_var[fbidx][vidx-1];
126 memcpy_tofs((void *) arg, &var, sizeof(var));
127 return i;
128 case FBIOPUT_VSCREENINFO:
129 i = verify_area(VERIFY_WRITE, (void *) arg,
130 sizeof(struct fb_var_screeninfo));
131 if (i) return i;
132 memcpy_fromfs(&var, (void *) arg, sizeof(var));
133 i=fb->fb_set_var(&var, PROC_CONSOLE());
134 memcpy_tofs((void *) arg, &var, sizeof(var));
135 fbidx=GET_FB_IDX(inode->i_rdev);
136 vidx=GET_FB_VAR_IDX(inode->i_rdev);
137 if (! i && vidx)
138 registered_fb_var[fbidx][vidx-1]=var;
139 return i;
140 case FBIOGET_FSCREENINFO:
141 i = verify_area(VERIFY_WRITE, (void *) arg,
142 sizeof(struct fb_fix_screeninfo));
143 if (i) return i;
144 i=fb->fb_get_fix(&fix, PROC_CONSOLE());
145 memcpy_tofs((void *) arg, &fix, sizeof(fix));
146 return i;
147 case FBIOPUTCMAP:
148 i = verify_area(VERIFY_READ, (void *) arg,
149 sizeof(struct fb_cmap));
150 if (i) return i;
151 memcpy_fromfs(&cmap, (void *) arg, sizeof(cmap));
152 i = verify_area(VERIFY_READ, (void *) cmap.red,
153 cmap.len * sizeof(unsigned short));
154 if (i) return i;
155 i = verify_area(VERIFY_READ, (void *) cmap.green,
156 cmap.len * sizeof(unsigned short));
157 if (i) return i;
158 i = verify_area(VERIFY_READ, (void *) cmap.blue,
159 cmap.len * sizeof(unsigned short));
160 if (i) return i;
161 if (cmap.transp) {
162 i = verify_area(VERIFY_READ, (void *) cmap.transp,
163 cmap.len * sizeof(unsigned short));
164 if (i) return i;
165 }
166 return (fb->fb_set_cmap(&cmap, 0, PROC_CONSOLE()));
167 case FBIOGETCMAP:
168 i = verify_area(VERIFY_READ, (void *) arg,
169 sizeof(struct fb_cmap));
170 if (i) return i;
171 memcpy_fromfs(&cmap, (void *) arg, sizeof(cmap));
172 i = verify_area(VERIFY_WRITE, (void *) cmap.red,
173 cmap.len * sizeof(unsigned short));
174 if (i) return i;
175 i = verify_area(VERIFY_WRITE, (void *) cmap.green,
176 cmap.len * sizeof(unsigned short));
177 if (i) return i;
178 i = verify_area(VERIFY_WRITE, (void *) cmap.blue,
179 cmap.len * sizeof(unsigned short));
180 if (i) return i;
181 if (cmap.transp) {
182 i = verify_area(VERIFY_WRITE, (void *) cmap.transp,
183 cmap.len * sizeof(unsigned short));
184 if (i) return i;
185 }
186 return (fb->fb_get_cmap(&cmap, 0, PROC_CONSOLE()));
187 case FBIOPAN_DISPLAY:
188 i = verify_area(VERIFY_WRITE, (void *) arg,
189 sizeof(struct fb_var_screeninfo));
190 if (i) return i;
191 memcpy_fromfs(&var, (void *) arg, sizeof(var));
192 i=fb->fb_pan_display(&var, PROC_CONSOLE());
193 memcpy_tofs((void *) arg, &var, sizeof(var));
194 fbidx=GET_FB_IDX(inode->i_rdev);
195 vidx=GET_FB_VAR_IDX(inode->i_rdev);
196 if (! i && vidx)
197 registered_fb_var[fbidx][vidx-1]=var;
198 return i;
199 default:
200 return (fb->fb_ioctl(inode, file, cmd, arg, PROC_CONSOLE()));
201 }
202 }
203
204 static int
205 fb_mmap(struct inode *inode, struct file *file, struct vm_area_struct * vma)
206 {
207 struct fb_ops *fb = registered_fb[GET_FB_IDX(inode->i_rdev)];
208 struct fb_fix_screeninfo fix;
209
210 if (! fb)
211 return -ENODEV;
212 fb->fb_get_fix(&fix, PROC_CONSOLE());
213 if ((vma->vm_end - vma->vm_start + vma->vm_offset) > fix.smem_len)
214 return -EINVAL;
215 vma->vm_offset += fix.smem_start;
216 if (vma->vm_offset & ~PAGE_MASK)
217 return -ENXIO;
218 if (m68k_is040or060) {
219 pgprot_val(vma->vm_page_prot) &= _CACHEMASK040;
220
221 pgprot_val(vma->vm_page_prot) |= _PAGE_CACHE040W;
222 }
223 if (remap_page_range(vma->vm_start, vma->vm_offset,
224 vma->vm_end - vma->vm_start, vma->vm_page_prot))
225 return -EAGAIN;
226 vma->vm_inode = inode;
227 inode->i_count++;
228 return 0;
229 }
230
231 static int
232 fb_open(struct inode *inode, struct file *file)
233 {
234 int fbidx=GET_FB_IDX(inode->i_rdev);
235 int vidx=GET_FB_VAR_IDX(inode->i_rdev);
236 struct fb_ops *fb = registered_fb[fbidx];
237 int err;
238
239 if (! vidx)
240 return 0;
241 if (vidx > registered_fb_var_num[fbidx])
242 return -EINVAL;
243 if (fb_curr_open[fbidx] && fb_curr_open[fbidx] != vidx)
244 return -EBUSY;
245 if (file->f_mode & 2)
246 if ((err=fb->fb_set_var(registered_fb_var[fbidx] + vidx-1, PROC_CONSOLE())))
247 return err;
248 fb_curr_open[fbidx] = vidx;
249 fb_open_count[fbidx]++;
250 return 0;
251 }
252
253 static void
254 fb_release(struct inode *inode, struct file *file)
255 {
256 int fbidx=GET_FB_IDX(inode->i_rdev);
257 int vidx=GET_FB_VAR_IDX(inode->i_rdev);
258 if (! vidx)
259 return;
260 if (! (--fb_open_count[fbidx]))
261 fb_curr_open[fbidx]=0;
262 }
263
264 static struct file_operations fb_fops = {
265 NULL,
266 fb_read,
267 fb_write,
268 NULL,
269 NULL,
270 fb_ioctl,
271 fb_mmap,
272 fb_open,
273 fb_release,
274 NULL
275 };
276
277 int
278 register_framebuffer(char *id, int *node, struct fb_ops *fbops, int fbvar_num,
279 struct fb_var_screeninfo *fbvar)
280 {
281 int i;
282 for (i = 0 ; i < FB_MAX; i++)
283 if (! registered_fb[i])
284 break;
285 if (i == FB_MAX)
286 return -ENXIO;
287 registered_fb[i]=fbops;
288 registered_fb_var[i]=fbvar;
289 registered_fb_var_num[i]=fbvar_num;
290 *node=GET_INODE(i);
291 return 0;
292 }
293
294 int
295 unregister_framebuffer(int node)
296 {
297 int i=GET_FB_IDX(node);
298 if (! registered_fb[i])
299 return -EINVAL;
300 registered_fb[i]=NULL;
301 registered_fb_var[i]=NULL;
302 return 0;
303 }
304
305 void
306 fbmem_init(void)
307 {
308 if (register_chrdev(FB_MAJOR,"fb",&fb_fops))
309 printk("unable to get major %d for fb devs\n", FB_MAJOR);
310 }
311