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