v2.4.9.9 -> v2.4.9.10
[opensuse:kernel.git] / drivers / video / fbmem.c
1 /*
2  *  linux/drivers/video/fbmem.c
3  *
4  *  Copyright (C) 1994 Martin Schaller
5  *
6  *      2001 - Documented with DocBook
7  *      - Brad Douglas <brad@neruo.com>
8  *
9  * This file is subject to the terms and conditions of the GNU General Public
10  * License.  See the file COPYING in the main directory of this archive
11  * for more details.
12  */
13
14 #include <linux/config.h>
15 #include <linux/module.h>
16
17 #include <linux/types.h>
18 #include <linux/errno.h>
19 #include <linux/sched.h>
20 #include <linux/smp_lock.h>
21 #include <linux/kernel.h>
22 #include <linux/major.h>
23 #include <linux/slab.h>
24 #include <linux/mman.h>
25 #include <linux/tty.h>
26 #include <linux/console.h>
27 #include <linux/init.h>
28 #include <linux/proc_fs.h>
29 #ifdef CONFIG_KMOD
30 #include <linux/kmod.h>
31 #endif
32 #include <linux/devfs_fs_kernel.h>
33
34 #if defined(__mc68000__) || defined(CONFIG_APUS)
35 #include <asm/setup.h>
36 #endif
37
38 #include <asm/io.h>
39 #include <asm/uaccess.h>
40 #include <asm/page.h>
41 #include <asm/pgtable.h>
42
43 #include <linux/fb.h>
44 #include <video/fbcon.h>
45
46     /*
47      *  Frame buffer device initialization and setup routines
48      */
49
50 extern int acornfb_init(void);
51 extern int acornfb_setup(char*);
52 extern int amifb_init(void);
53 extern int amifb_setup(char*);
54 extern int atafb_init(void);
55 extern int atafb_setup(char*);
56 extern int macfb_init(void);
57 extern int macfb_setup(char*);
58 extern int cyberfb_init(void);
59 extern int cyberfb_setup(char*);
60 extern int pm2fb_init(void);
61 extern int pm2fb_setup(char*);
62 extern int cyber2000fb_init(void);
63 extern int retz3fb_init(void);
64 extern int retz3fb_setup(char*);
65 extern int clgenfb_init(void);
66 extern int clgenfb_setup(char*);
67 extern int hitfb_init(void);
68 extern int vfb_init(void);
69 extern int vfb_setup(char*);
70 extern int offb_init(void);
71 extern int atyfb_init(void);
72 extern int atyfb_setup(char*);
73 extern int aty128fb_init(void);
74 extern int aty128fb_setup(char*);
75 extern int igafb_init(void);
76 extern int igafb_setup(char*);
77 extern int imsttfb_init(void);
78 extern int imsttfb_setup(char*);
79 extern int dnfb_init(void);
80 extern int tgafb_init(void);
81 extern int tgafb_setup(char*);
82 extern int virgefb_init(void);
83 extern int virgefb_setup(char*);
84 extern int resolver_video_setup(char*);
85 extern int s3triofb_init(void);
86 extern int vesafb_init(void);
87 extern int vesafb_setup(char*);
88 extern int vga16fb_init(void);
89 extern int vga16fb_setup(char*);
90 extern int hgafb_init(void);
91 extern int hgafb_setup(char*);
92 extern int matroxfb_init(void);
93 extern int matroxfb_setup(char*);
94 extern int hpfb_init(void);
95 extern int sbusfb_init(void);
96 extern int sbusfb_setup(char*);
97 extern int control_init(void);
98 extern int control_setup(char*);
99 extern int platinum_init(void);
100 extern int platinum_setup(char*);
101 extern int valkyriefb_init(void);
102 extern int valkyriefb_setup(char*);
103 extern int chips_init(void);
104 extern int g364fb_init(void);
105 extern int sa1100fb_init(void);
106 extern int fm2fb_init(void);
107 extern int fm2fb_setup(char*);
108 extern int q40fb_init(void);
109 extern int sun3fb_init(void);
110 extern int sun3fb_setup(char *);
111 extern int sgivwfb_init(void);
112 extern int sgivwfb_setup(char*);
113 extern int rivafb_init(void);
114 extern int rivafb_setup(char*);
115 extern int tdfxfb_init(void);
116 extern int tdfxfb_setup(char*);
117 extern int sisfb_init(void);
118 extern int sisfb_setup(char*);
119 extern int stifb_init(void);
120 extern int stifb_setup(char*);
121 extern int radeonfb_init(void);
122 extern int radeonfb_setup(char*);
123 extern int e1355fb_init(void);
124 extern int e1355fb_setup(char*);
125 extern int pvr2fb_init(void);
126 extern int pvr2fb_setup(char*);
127
128 static struct {
129         const char *name;
130         int (*init)(void);
131         int (*setup)(char*);
132 } fb_drivers[] __initdata = {
133
134 #ifdef CONFIG_FB_SBUS
135         /*
136          * Sbusfb must be initialized _before_ other frame buffer devices that
137          * use PCI probing
138          */
139         { "sbus", sbusfb_init, sbusfb_setup },
140 #endif
141
142         /*
143          * Chipset specific drivers that use resource management
144          */
145
146 #ifdef CONFIG_FB_RETINAZ3
147         { "retz3", retz3fb_init, retz3fb_setup },
148 #endif
149 #ifdef CONFIG_FB_AMIGA
150         { "amifb", amifb_init, amifb_setup },
151 #endif
152 #ifdef CONFIG_FB_CYBER
153         { "cyber", cyberfb_init, cyberfb_setup },
154 #endif
155 #ifdef CONFIG_FB_CYBER2000
156         { "cyber2000", cyber2000fb_init, NULL },
157 #endif
158 #ifdef CONFIG_FB_PM2
159         { "pm2fb", pm2fb_init, pm2fb_setup },
160 #endif
161 #ifdef CONFIG_FB_CLGEN
162         { "clgen", clgenfb_init, clgenfb_setup },
163 #endif
164 #ifdef CONFIG_FB_ATY
165         { "atyfb", atyfb_init, atyfb_setup },
166 #endif
167 #ifdef CONFIG_FB_MATROX
168         { "matrox", matroxfb_init, matroxfb_setup },
169 #endif
170 #ifdef CONFIG_FB_ATY128
171         { "aty128fb", aty128fb_init, aty128fb_setup },
172 #endif
173 #ifdef CONFIG_FB_VIRGE
174         { "virge", virgefb_init, virgefb_setup },
175 #endif
176 #ifdef CONFIG_FB_RIVA
177         { "riva", rivafb_init, rivafb_setup },
178 #endif
179 #ifdef CONFIG_FB_RADEON
180         { "radeon", radeonfb_init, radeonfb_setup },
181 #endif
182 #ifdef CONFIG_FB_CONTROL
183         { "controlfb", control_init, control_setup },
184 #endif
185 #ifdef CONFIG_FB_PLATINUM
186         { "platinumfb", platinum_init, platinum_setup },
187 #endif
188 #ifdef CONFIG_FB_VALKYRIE
189         { "valkyriefb", valkyriefb_init, valkyriefb_setup },
190 #endif
191 #ifdef CONFIG_FB_CT65550
192         { "chipsfb", chips_init, NULL },
193 #endif
194 #ifdef CONFIG_FB_IMSTT
195         { "imsttfb", imsttfb_init, imsttfb_setup },
196 #endif
197 #ifdef CONFIG_FB_S3TRIO
198         { "s3trio", s3triofb_init, NULL },
199 #endif 
200 #ifdef CONFIG_FB_FM2
201         { "fm2fb", fm2fb_init, fm2fb_setup },
202 #endif 
203 #ifdef CONFIG_FB_SIS
204         { "sisfb", sisfb_init, sisfb_setup },
205 #endif
206
207         /*
208          * Generic drivers that are used as fallbacks
209          * 
210          * These depend on resource management and must be initialized
211          * _after_ all other frame buffer devices that use resource
212          * management!
213          */
214
215 #ifdef CONFIG_FB_OF
216         { "offb", offb_init, NULL },
217 #endif
218 #ifdef CONFIG_FB_VESA
219         { "vesa", vesafb_init, vesafb_setup },
220 #endif 
221
222         /*
223          * Chipset specific drivers that don't use resource management (yet)
224          */
225
226 #ifdef CONFIG_FB_3DFX
227         { "tdfx", tdfxfb_init, tdfxfb_setup },
228 #endif
229 #ifdef CONFIG_FB_SGIVW
230         { "sgivw", sgivwfb_init, sgivwfb_setup },
231 #endif
232 #ifdef CONFIG_FB_ACORN
233         { "acorn", acornfb_init, acornfb_setup },
234 #endif
235 #ifdef CONFIG_FB_ATARI
236         { "atafb", atafb_init, atafb_setup },
237 #endif
238 #ifdef CONFIG_FB_MAC
239         { "macfb", macfb_init, macfb_setup },
240 #endif
241 #ifdef CONFIG_FB_HGA
242         { "hga", hgafb_init, hgafb_setup },
243 #endif 
244 #ifdef CONFIG_FB_IGA
245         { "igafb", igafb_init, igafb_setup },
246 #endif
247 #ifdef CONFIG_APOLLO
248         { "apollo", dnfb_init, NULL },
249 #endif
250 #ifdef CONFIG_FB_Q40
251         { "q40fb", q40fb_init, NULL },
252 #endif
253 #ifdef CONFIG_FB_TGA
254         { "tga", tgafb_init, tgafb_setup },
255 #endif
256 #ifdef CONFIG_FB_HP300
257         { "hpfb", hpfb_init, NULL },
258 #endif 
259 #ifdef CONFIG_FB_G364
260         { "g364", g364fb_init, NULL },
261 #endif
262 #ifdef CONFIG_FB_SA1100
263         { "sa1100", sa1100fb_init, NULL },
264 #endif
265 #ifdef CONFIG_FB_SUN3
266         { "sun3", sun3fb_init, sun3fb_setup },
267 #endif
268 #ifdef CONFIG_FB_HIT
269         { "hitfb", hitfb_init, NULL },
270 #endif
271 #ifdef CONFIG_FB_E1355
272         { "e1355fb", e1355fb_init, e1355fb_setup },
273 #endif
274 #ifdef CONFIG_FB_PVR2
275         { "pvr2", pvr2fb_init, pvr2fb_setup },
276 #endif
277
278         /*
279          * Generic drivers that don't use resource management (yet)
280          */
281
282 #ifdef CONFIG_FB_VGA16
283         { "vga16", vga16fb_init, vga16fb_setup },
284 #endif 
285 #ifdef CONFIG_FB_STI
286         { "stifb", stifb_init, stifb_setup },
287 #endif
288
289 #ifdef CONFIG_GSP_RESOLVER
290         /* Not a real frame buffer device... */
291         { "resolver", NULL, resolver_video_setup },
292 #endif
293
294 #ifdef CONFIG_FB_VIRTUAL
295         /*
296          * Vfb must be last to avoid that it becomes your primary display if
297          * other display devices are present
298          */
299         { "vfb", vfb_init, vfb_setup },
300 #endif
301 };
302
303 #define NUM_FB_DRIVERS  (sizeof(fb_drivers)/sizeof(*fb_drivers))
304
305 extern const char *global_mode_option;
306
307 static initcall_t pref_init_funcs[FB_MAX];
308 static int num_pref_init_funcs __initdata = 0;
309
310
311 struct fb_info *registered_fb[FB_MAX];
312 int num_registered_fb;
313 extern int fbcon_softback_size; 
314
315 static int first_fb_vc;
316 static int last_fb_vc = MAX_NR_CONSOLES-1;
317 static int fbcon_is_default = 1;
318
319 #ifdef CONFIG_FB_OF
320 static int ofonly __initdata = 0;
321 #endif
322
323 static int fbmem_read_proc(char *buf, char **start, off_t offset,
324                            int len, int *eof, void *private)
325 {
326         struct fb_info **fi;
327         int clen;
328
329         clen = 0;
330         for (fi = registered_fb; fi < &registered_fb[FB_MAX] && len < 4000; fi++)
331                 if (*fi)
332                         clen += sprintf(buf + clen, "%d %s\n",
333                                         GET_FB_IDX((*fi)->node),
334                                         (*fi)->modename);
335         *start = buf + offset;
336         if (clen > offset)
337                 clen -= offset;
338         else
339                 clen = 0;
340         return clen < len ? clen : len;
341 }
342
343 static ssize_t
344 fb_read(struct file *file, char *buf, size_t count, loff_t *ppos)
345 {
346         unsigned long p = *ppos;
347         struct inode *inode = file->f_dentry->d_inode;
348         int fbidx = GET_FB_IDX(inode->i_rdev);
349         struct fb_info *info = registered_fb[fbidx];
350         struct fb_ops *fb = info->fbops;
351         struct fb_fix_screeninfo fix;
352
353         if (! fb || ! info->disp)
354                 return -ENODEV;
355
356         fb->fb_get_fix(&fix,PROC_CONSOLE(info), info);
357         if (p >= fix.smem_len)
358             return 0;
359         if (count >= fix.smem_len)
360             count = fix.smem_len;
361         if (count + p > fix.smem_len)
362                 count = fix.smem_len - p;
363         if (count) {
364             char *base_addr;
365
366             base_addr = info->disp->screen_base;
367             count -= copy_to_user(buf, base_addr+p, count);
368             if (!count)
369                 return -EFAULT;
370             *ppos += count;
371         }
372         return count;
373 }
374
375 static ssize_t
376 fb_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
377 {
378         unsigned long p = *ppos;
379         struct inode *inode = file->f_dentry->d_inode;
380         int fbidx = GET_FB_IDX(inode->i_rdev);
381         struct fb_info *info = registered_fb[fbidx];
382         struct fb_ops *fb = info->fbops;
383         struct fb_fix_screeninfo fix;
384         int err;
385
386         if (! fb || ! info->disp)
387                 return -ENODEV;
388
389         fb->fb_get_fix(&fix, PROC_CONSOLE(info), info);
390         if (p > fix.smem_len)
391             return -ENOSPC;
392         if (count >= fix.smem_len)
393             count = fix.smem_len;
394         err = 0;
395         if (count + p > fix.smem_len) {
396             count = fix.smem_len - p;
397             err = -ENOSPC;
398         }
399         if (count) {
400             char *base_addr;
401
402             base_addr = info->disp->screen_base;
403             count -= copy_from_user(base_addr+p, buf, count);
404             *ppos += count;
405             err = -EFAULT;
406         }
407         if (count)
408                 return count;
409         return err;
410 }
411
412 #ifdef CONFIG_KMOD
413 static void try_to_load(int fb)
414 {
415         char modname[16];
416
417         sprintf(modname, "fb%d", fb);
418         request_module(modname);
419 }
420 #endif /* CONFIG_KMOD */
421
422 static int 
423 fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
424          unsigned long arg)
425 {
426         int fbidx = GET_FB_IDX(inode->i_rdev);
427         struct fb_info *info = registered_fb[fbidx];
428         struct fb_ops *fb = info->fbops;
429         struct fb_cmap cmap;
430         struct fb_var_screeninfo var;
431         struct fb_fix_screeninfo fix;
432         struct fb_con2fbmap con2fb;
433         int i;
434         
435         if (! fb)
436                 return -ENODEV;
437         switch (cmd) {
438         case FBIOGET_VSCREENINFO:
439                 if ((i = fb->fb_get_var(&var, PROC_CONSOLE(info), info)))
440                         return i;
441                 return copy_to_user((void *) arg, &var,
442                                     sizeof(var)) ? -EFAULT : 0;
443         case FBIOPUT_VSCREENINFO:
444                 if (copy_from_user(&var, (void *) arg, sizeof(var)))
445                         return -EFAULT;
446                 i = var.activate & FB_ACTIVATE_ALL
447                             ? set_all_vcs(fbidx, fb, &var, info)
448                             : fb->fb_set_var(&var, PROC_CONSOLE(info), info);
449                 if (i)
450                         return i;
451                 if (copy_to_user((void *) arg, &var, sizeof(var)))
452                         return -EFAULT;
453                 return 0;
454         case FBIOGET_FSCREENINFO:
455                 if ((i = fb->fb_get_fix(&fix, PROC_CONSOLE(info), info)))
456                         return i;
457                 return copy_to_user((void *) arg, &fix, sizeof(fix)) ?
458                         -EFAULT : 0;
459         case FBIOPUTCMAP:
460                 if (copy_from_user(&cmap, (void *) arg, sizeof(cmap)))
461                         return -EFAULT;
462                 return (fb->fb_set_cmap(&cmap, 0, PROC_CONSOLE(info), info));
463         case FBIOGETCMAP:
464                 if (copy_from_user(&cmap, (void *) arg, sizeof(cmap)))
465                         return -EFAULT;
466                 return (fb->fb_get_cmap(&cmap, 0, PROC_CONSOLE(info), info));
467         case FBIOPAN_DISPLAY:
468                 if (copy_from_user(&var, (void *) arg, sizeof(var)))
469                         return -EFAULT;
470                 if (fb->fb_pan_display == NULL)
471                         return (var.xoffset || var.yoffset) ? -EINVAL : 0;
472                 if ((i=fb->fb_pan_display(&var, PROC_CONSOLE(info), info)))
473                         return i;
474                 if (copy_to_user((void *) arg, &var, sizeof(var)))
475                         return -EFAULT;
476                 return i;
477         case FBIOGET_CON2FBMAP:
478                 if (copy_from_user(&con2fb, (void *)arg, sizeof(con2fb)))
479                         return -EFAULT;
480                 if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)
481                     return -EINVAL;
482                 con2fb.framebuffer = con2fb_map[con2fb.console-1];
483                 return copy_to_user((void *)arg, &con2fb,
484                                     sizeof(con2fb)) ? -EFAULT : 0;
485         case FBIOPUT_CON2FBMAP:
486                 if (copy_from_user(&con2fb, (void *)arg, sizeof(con2fb)))
487                         return - EFAULT;
488                 if (con2fb.console < 0 || con2fb.console > MAX_NR_CONSOLES)
489                     return -EINVAL;
490                 if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX)
491                     return -EINVAL;
492 #ifdef CONFIG_KMOD
493                 if (!registered_fb[con2fb.framebuffer])
494                     try_to_load(con2fb.framebuffer);
495 #endif /* CONFIG_KMOD */
496                 if (!registered_fb[con2fb.framebuffer])
497                     return -EINVAL;
498                 if (con2fb.console != 0)
499                     set_con2fb_map(con2fb.console-1, con2fb.framebuffer);
500                 else
501                     /* set them all */
502                     for (i = 0; i < MAX_NR_CONSOLES; i++)
503                         set_con2fb_map(i, con2fb.framebuffer);
504                 return 0;
505         case FBIOBLANK:
506                 if (info->blank == 0)
507                         return -EINVAL;
508                 (*info->blank)(arg, info);
509                 return 0;
510         default:
511                 if (fb->fb_ioctl == NULL)
512                         return -EINVAL;
513                 return fb->fb_ioctl(inode, file, cmd, arg, PROC_CONSOLE(info),
514                                     info);
515         }
516 }
517
518 static int 
519 fb_mmap(struct file *file, struct vm_area_struct * vma)
520 {
521         int fbidx = GET_FB_IDX(file->f_dentry->d_inode->i_rdev);
522         struct fb_info *info = registered_fb[fbidx];
523         struct fb_ops *fb = info->fbops;
524         unsigned long off;
525 #if !defined(__sparc__) || defined(__sparc_v9__)
526         struct fb_fix_screeninfo fix;
527         struct fb_var_screeninfo var;
528         unsigned long start;
529         u32 len;
530 #endif
531
532         if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
533                 return -EINVAL;
534         off = vma->vm_pgoff << PAGE_SHIFT;
535         if (!fb)
536                 return -ENODEV;
537         if (fb->fb_mmap) {
538                 int res;
539                 lock_kernel();
540                 res = fb->fb_mmap(info, file, vma);
541                 unlock_kernel();
542                 return res;
543         }
544
545 #if defined(__sparc__) && !defined(__sparc_v9__)
546         /* Should never get here, all fb drivers should have their own
547            mmap routines */
548         return -EINVAL;
549 #else
550         /* !sparc32... */
551
552         lock_kernel();
553         fb->fb_get_fix(&fix, PROC_CONSOLE(info), info);
554
555         /* frame buffer memory */
556         start = fix.smem_start;
557         len = PAGE_ALIGN((start & ~PAGE_MASK)+fix.smem_len);
558         if (off >= len) {
559                 /* memory mapped io */
560                 off -= len;
561                 fb->fb_get_var(&var, PROC_CONSOLE(info), info);
562                 if (var.accel_flags)
563                         return -EINVAL;
564                 start = fix.mmio_start;
565                 len = PAGE_ALIGN((start & ~PAGE_MASK)+fix.mmio_len);
566         }
567         unlock_kernel();
568         start &= PAGE_MASK;
569         if ((vma->vm_end - vma->vm_start + off) > len)
570                 return -EINVAL;
571         off += start;
572         vma->vm_pgoff = off >> PAGE_SHIFT;
573 #if defined(__sparc_v9__)
574         vma->vm_flags |= (VM_SHM | VM_LOCKED);
575         if (io_remap_page_range(vma->vm_start, off,
576                                 vma->vm_end - vma->vm_start, vma->vm_page_prot, 0))
577                 return -EAGAIN;
578         vma->vm_flags |= VM_IO;
579 #else
580 #if defined(__mc68000__)
581 #if defined(CONFIG_SUN3)
582         pgprot_val(vma->vm_page_prot) |= SUN3_PAGE_NOCACHE;
583 #else
584         if (CPU_IS_020_OR_030)
585                 pgprot_val(vma->vm_page_prot) |= _PAGE_NOCACHE030;
586         if (CPU_IS_040_OR_060) {
587                 pgprot_val(vma->vm_page_prot) &= _CACHEMASK040;
588                 /* Use no-cache mode, serialized */
589                 pgprot_val(vma->vm_page_prot) |= _PAGE_NOCACHE_S;
590         }
591 #endif
592 #elif defined(__powerpc__)
593         pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE|_PAGE_GUARDED;
594 #elif defined(__alpha__)
595         /* Caching is off in the I/O space quadrant by design.  */
596 #elif defined(__i386__) || defined(__x86_64__)
597         if (boot_cpu_data.x86 > 3)
598                 pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
599 #elif defined(__mips__)
600         pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK;
601         pgprot_val(vma->vm_page_prot) |= _CACHE_UNCACHED;
602 #elif defined(__arm__)
603         vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
604         /* This is an IO map - tell maydump to skip this VMA */
605         vma->vm_flags |= VM_IO;
606 #elif defined(__sh__)
607         pgprot_val(vma->vm_page_prot) &= ~_PAGE_CACHABLE;
608 #else
609 #warning What do we have to do here??
610 #endif
611         if (io_remap_page_range(vma->vm_start, off,
612                              vma->vm_end - vma->vm_start, vma->vm_page_prot))
613                 return -EAGAIN;
614 #endif /* !__sparc_v9__ */
615         return 0;
616 #endif /* !sparc32 */
617 }
618
619 #if 1 /* to go away in 2.5.0 */
620 int GET_FB_IDX(kdev_t rdev)
621 {
622     int fbidx = MINOR(rdev);
623     if (fbidx >= 32) {
624         int newfbidx = fbidx >> 5;
625         static int warned;
626         if (!(warned & (1<<newfbidx))) {
627             warned |= 1<<newfbidx;
628             printk("Warning: Remapping obsolete /dev/fb* minor %d to %d\n",
629                    fbidx, newfbidx);
630         }
631         fbidx = newfbidx;
632     }
633     return fbidx;
634 }
635 #endif
636
637 static int
638 fb_open(struct inode *inode, struct file *file)
639 {
640         int fbidx = GET_FB_IDX(inode->i_rdev);
641         struct fb_info *info;
642         int res = 0;
643
644 #ifdef CONFIG_KMOD
645         if (!(info = registered_fb[fbidx]))
646                 try_to_load(fbidx);
647 #endif /* CONFIG_KMOD */
648         if (!(info = registered_fb[fbidx]))
649                 return -ENODEV;
650         if (info->fbops->owner)
651                 __MOD_INC_USE_COUNT(info->fbops->owner);
652         if (info->fbops->fb_open) {
653                 res = info->fbops->fb_open(info,1);
654                 if (res && info->fbops->owner)
655                         __MOD_DEC_USE_COUNT(info->fbops->owner);
656         }
657         return res;
658 }
659
660 static int 
661 fb_release(struct inode *inode, struct file *file)
662 {
663         int fbidx = GET_FB_IDX(inode->i_rdev);
664         struct fb_info *info;
665
666         lock_kernel();
667         info = registered_fb[fbidx];
668         if (info->fbops->fb_release)
669                 info->fbops->fb_release(info,1);
670         if (info->fbops->owner)
671                 __MOD_DEC_USE_COUNT(info->fbops->owner);
672         unlock_kernel();
673         return 0;
674 }
675
676 static struct file_operations fb_fops = {
677         owner:          THIS_MODULE,
678         read:           fb_read,
679         write:          fb_write,
680         ioctl:          fb_ioctl,
681         mmap:           fb_mmap,
682         open:           fb_open,
683         release:        fb_release,
684 #ifdef HAVE_ARCH_FB_UNMAPPED_AREA
685         get_unmapped_area: get_fb_unmapped_area,
686 #endif
687 };
688
689 static devfs_handle_t devfs_handle;
690
691
692 /**
693  *      register_framebuffer - registers a frame buffer device
694  *      @fb_info: frame buffer info structure
695  *
696  *      Registers a frame buffer device @fb_info.
697  *
698  *      Returns negative errno on error, or zero for success.
699  *
700  */
701
702 int
703 register_framebuffer(struct fb_info *fb_info)
704 {
705         int i, j;
706         char name_buf[8];
707         static int fb_ever_opened[FB_MAX];
708         static int first = 1;
709
710         if (num_registered_fb == FB_MAX)
711                 return -ENXIO;
712         num_registered_fb++;
713         for (i = 0 ; i < FB_MAX; i++)
714                 if (!registered_fb[i])
715                         break;
716         fb_info->node = MKDEV(FB_MAJOR, i);
717         registered_fb[i] = fb_info;
718         if (!fb_ever_opened[i]) {
719                 struct module *owner = fb_info->fbops->owner;
720                 /*
721                  *  We assume initial frame buffer devices can be opened this
722                  *  many times
723                  */
724                 for (j = 0; j < MAX_NR_CONSOLES; j++)
725                         if (con2fb_map[j] == i) {
726                                 if (owner)
727                                         __MOD_INC_USE_COUNT(owner);
728                                 if (!fb_info->fbops->fb_open)
729                                         continue;
730                                 if (!fb_info->fbops->fb_open(fb_info,0))
731                                         continue;
732                                 if (owner)
733                                         __MOD_DEC_USE_COUNT(owner);
734                         }
735                 fb_ever_opened[i] = 1;
736         }
737
738         if (first) {
739                 first = 0;
740                 take_over_console(&fb_con, first_fb_vc, last_fb_vc, fbcon_is_default);
741         }
742         sprintf (name_buf, "%d", i);
743         fb_info->devfs_handle =
744             devfs_register (devfs_handle, name_buf, DEVFS_FL_DEFAULT,
745                             FB_MAJOR, i, S_IFCHR | S_IRUGO | S_IWUGO,
746                             &fb_fops, NULL);
747
748         return 0;
749 }
750
751
752 /**
753  *      unregister_framebuffer - releases a frame buffer device
754  *      @fb_info: frame buffer info structure
755  *
756  *      Unregisters a frame buffer device @fb_info.
757  *
758  *      Returns negative errno on error, or zero for success.
759  *
760  */
761
762 int
763 unregister_framebuffer(struct fb_info *fb_info)
764 {
765         int i, j;
766
767         i = GET_FB_IDX(fb_info->node);
768         for (j = 0; j < MAX_NR_CONSOLES; j++)
769                 if (con2fb_map[j] == i)
770                         return -EBUSY;
771         if (!registered_fb[i])
772                 return -EINVAL;
773         devfs_unregister (fb_info->devfs_handle);
774         fb_info->devfs_handle = NULL;
775         devfs_unregister (fb_info->devfs_lhandle);
776         fb_info->devfs_lhandle = NULL;
777         registered_fb[i]=NULL;
778         num_registered_fb--;
779         return 0;
780 }
781
782
783 /**
784  *      fbmem_init - init frame buffer subsystem
785  *
786  *      Initialize the frame buffer subsystem.
787  *
788  *      NOTE: This function is _only_ to be called by drivers/char/mem.c.
789  *
790  */
791
792 void __init 
793 fbmem_init(void)
794 {
795         int i;
796
797         create_proc_read_entry("fb", 0, 0, fbmem_read_proc, NULL);
798
799         devfs_handle = devfs_mk_dir (NULL, "fb", NULL);
800         if (devfs_register_chrdev(FB_MAJOR,"fb",&fb_fops))
801                 printk("unable to get major %d for fb devs\n", FB_MAJOR);
802
803 #ifdef CONFIG_FB_OF
804         if (ofonly) {
805                 offb_init();
806                 return;
807         }
808 #endif
809
810         /*
811          *  Probe for all builtin frame buffer devices
812          */
813         for (i = 0; i < num_pref_init_funcs; i++)
814                 pref_init_funcs[i]();
815
816         for (i = 0; i < NUM_FB_DRIVERS; i++)
817                 if (fb_drivers[i].init)
818                         fb_drivers[i].init();
819 }
820
821
822 /**
823  *      video_setup - process command line options
824  *      @options: string of options
825  *
826  *      Process command line options for frame buffer subsystem.
827  *
828  *      NOTE: This function is a __setup and __init function.
829  *
830  *      Returns zero.
831  *
832  */
833
834 int __init video_setup(char *options)
835 {
836     int i, j;
837
838     if (!options || !*options)
839             return 0;
840             
841     if (!strncmp(options, "scrollback:", 11)) {
842             options += 11;
843             if (*options) {
844                 fbcon_softback_size = simple_strtoul(options, &options, 0);
845                 if (*options == 'k' || *options == 'K') {
846                         fbcon_softback_size *= 1024;
847                         options++;
848                 }
849                 if (*options != ',')
850                         return 0;
851                 options++;
852             } else
853                 return 0;
854     }
855
856     if (!strncmp(options, "map:", 4)) {
857             options += 4;
858             if (*options)
859                     for (i = 0, j = 0; i < MAX_NR_CONSOLES; i++) {
860                             if (!options[j])
861                                     j = 0;
862                             con2fb_map[i] = (options[j++]-'0') % FB_MAX;
863                     }
864             return 0;
865     }
866     
867     if (!strncmp(options, "vc:", 3)) {
868             options += 3;
869             if (*options)
870                 first_fb_vc = simple_strtoul(options, &options, 10) - 1;
871             if (first_fb_vc < 0)
872                 first_fb_vc = 0;
873             if (*options++ == '-')
874                 last_fb_vc = simple_strtoul(options, &options, 10) - 1;
875             fbcon_is_default = 0;
876     }
877
878 #ifdef CONFIG_FB_OF
879     if (!strcmp(options, "ofonly")) {
880             ofonly = 1;
881             return 0;
882     }
883 #endif
884
885     if (num_pref_init_funcs == FB_MAX)
886             return 0;
887
888     for (i = 0; i < NUM_FB_DRIVERS; i++) {
889             j = strlen(fb_drivers[i].name);
890             if (!strncmp(options, fb_drivers[i].name, j) &&
891                 options[j] == ':') {
892                     if (!strcmp(options+j+1, "off"))
893                             fb_drivers[i].init = NULL;
894                     else {
895                             if (fb_drivers[i].init) {
896                                     pref_init_funcs[num_pref_init_funcs++] =
897                                             fb_drivers[i].init;
898                                     fb_drivers[i].init = NULL;
899                             }
900                             if (fb_drivers[i].setup)
901                                     fb_drivers[i].setup(options+j+1);
902                     }
903                     return 0;
904             }
905     }
906
907     /*
908      * If we get here no fb was specified.
909      * We consider the argument to be a global video mode option.
910      */
911     global_mode_option = options;
912     return 0;
913 }
914
915 __setup("video=", video_setup);
916
917     /*
918      *  Visible symbols for modules
919      */
920
921 EXPORT_SYMBOL(register_framebuffer);
922 EXPORT_SYMBOL(unregister_framebuffer);
923 EXPORT_SYMBOL(registered_fb);
924 EXPORT_SYMBOL(num_registered_fb);
925 #if 1 /* to go away in 2.5.0 */
926 EXPORT_SYMBOL(GET_FB_IDX);
927 #endif