Subversion Repositories shark

Rev

Rev 472 | Rev 476 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
466 giacomo 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 <linuxcomp.h>
15
 
16
#include <linux/config.h>
17
#include <linux/module.h>
18
 
19
#include <linux/types.h>
20
#include <linux/errno.h>
21
#include <linux/sched.h>
22
#include <linux/smp_lock.h>
23
#include <linux/kernel.h>
24
#include <linux/major.h>
25
#include <linux/slab.h>
26
#include <linux/mm.h>
27
#include <linux/mman.h>
28
#include <linux/tty.h>
29
#include <linux/init.h>
30
#include <linux/linux_logo.h>
31
#include <linux/proc_fs.h>
32
#ifdef CONFIG_KMOD
33
#include <linux/kmod.h>
34
#endif
35
#include <linux/devfs_fs_kernel.h>
36
 
37
#if defined(__mc68000__) || defined(CONFIG_APUS)
38
#include <asm/setup.h>
39
#endif
40
 
41
#include <asm/io.h>
42
#include <asm/uaccess.h>
43
#include <asm/page.h>
44
#include <asm/pgtable.h>
45
 
46
#include <linux/fb.h>
47
 
48
#ifdef CONFIG_FRAMEBUFFER_CONSOLE
49
#include "console/fbcon.h"
50
#endif
51
    /*
52
     *  Frame buffer device initialization and setup routines
53
     */
54
 
55
extern int acornfb_init(void);
56
extern int acornfb_setup(char*);
57
extern int amifb_init(void);
58
extern int amifb_setup(char*);
59
extern int anakinfb_init(void);
60
extern int atafb_init(void);
61
extern int atafb_setup(char*);
62
extern int macfb_init(void);
63
extern int macfb_setup(char*);
64
extern int cyberfb_init(void);
65
extern int cyberfb_setup(char*);
66
extern int pm2fb_init(void);
67
extern int pm2fb_setup(char*);
68
extern int pm3fb_init(void);
69
extern int pm3fb_setup(char*);
70
extern int clps711xfb_init(void);
71
extern int cyber2000fb_init(void);
72
extern int cyber2000fb_setup(char*);
73
extern int retz3fb_init(void);
74
extern int retz3fb_setup(char*);
75
extern int clgenfb_init(void);
76
extern int clgenfb_setup(char*);
77
extern int hitfb_init(void);
78
extern int vfb_init(void);
79
extern int vfb_setup(char*);
80
extern int offb_init(void);
81
extern int atyfb_init(void);
82
extern int atyfb_setup(char*);
83
extern int aty128fb_init(void);
84
extern int aty128fb_setup(char*);
85
extern int neofb_init(void);
86
extern int neofb_setup(char*);
87
extern int igafb_init(void);
88
extern int igafb_setup(char*);
89
extern int imsttfb_init(void);
90
extern int imsttfb_setup(char*);
91
extern int dnfb_init(void);
92
extern int tgafb_init(void);
93
extern int tgafb_setup(char*);
94
extern int virgefb_init(void);
95
extern int virgefb_setup(char*);
96
extern int resolver_video_setup(char*);
97
extern int s3triofb_init(void);
98
extern int vesafb_init(void);
99
extern int vesafb_setup(char*);
100
extern int vga16fb_init(void);
101
extern int vga16fb_setup(char*);
102
extern int hgafb_init(void);
103
extern int hgafb_setup(char*);
104
extern int matroxfb_init(void);
105
extern int matroxfb_setup(char*);
106
extern int hpfb_init(void);
107
extern int control_init(void);
108
extern int control_setup(char*);
109
extern int platinum_init(void);
110
extern int platinum_setup(char*);
111
extern int valkyriefb_init(void);
112
extern int valkyriefb_setup(char*);
113
extern int chips_init(void);
114
extern int g364fb_init(void);
115
extern int sa1100fb_init(void);
116
extern int fm2fb_init(void);
117
extern int fm2fb_setup(char*);
118
extern int q40fb_init(void);
119
extern int sun3fb_init(void);
120
extern int sun3fb_setup(char *);
121
extern int sgivwfb_init(void);
122
extern int sgivwfb_setup(char*);
123
extern int rivafb_init(void);
124
extern int rivafb_setup(char*);
125
extern int tdfxfb_init(void);
126
extern int tdfxfb_setup(char*);
127
extern int tridentfb_init(void);
128
extern int tridentfb_setup(char*);
129
extern int sisfb_init(void);
130
extern int sisfb_setup(char*);
131
extern int stifb_init(void);
132
extern int stifb_setup(char*);
133
extern int pmagbafb_init(void);
134
extern int pmagbbfb_init(void);
135
extern int maxinefb_init(void);
136
extern int tx3912fb_init(void);
137
extern int tx3912fb_setup(char*);
138
extern int radeonfb_init(void);
139
extern int radeonfb_setup(char*);
140
extern int e1355fb_init(void);
141
extern int e1355fb_setup(char*);
142
extern int pvr2fb_init(void);
143
extern int pvr2fb_setup(char*);
144
extern int sstfb_init(void);
145
extern int sstfb_setup(char*);
146
extern int i810fb_init(void);
147
extern int i810fb_setup(char*);
148
extern int ffb_init(void);
149
extern int ffb_setup(char*);
150
extern int cg6_init(void);
151
extern int cg6_setup(char*);
152
extern int cg3_init(void);
153
extern int cg3_setup(char*);
154
extern int bw2_init(void);
155
extern int bw2_setup(char*);
156
extern int cg14_init(void);
157
extern int cg14_setup(char*);
158
extern int p9100_init(void);
159
extern int p9100_setup(char*);
160
extern int tcx_init(void);
161
extern int tcx_setup(char*);
162
extern int leo_init(void);
163
extern int leo_setup(char*);
164
 
165
static struct {
166
        const char *name;
167
        int (*init)(void);
168
        int (*setup)(char*);
169
} fb_drivers[] __initdata = {
170
 
171
        /*
172
         * Chipset specific drivers that use resource management
173
         */
174
#ifdef CONFIG_FB_RETINAZ3
175
        { "retz3fb", retz3fb_init, retz3fb_setup },
176
#endif
177
#ifdef CONFIG_FB_AMIGA
178
        { "amifb", amifb_init, amifb_setup },
179
#endif
180
#ifdef CONFIG_FB_ANAKIN
181
        { "anakinfb", anakinfb_init, NULL },
182
#endif
183
#ifdef CONFIG_FB_CLPS711X
184
        { "clps711xfb", clps711xfb_init, NULL },
185
#endif
186
#ifdef CONFIG_FB_CYBER
187
        { "cyberfb", cyberfb_init, cyberfb_setup },
188
#endif
189
#ifdef CONFIG_FB_CYBER2000
190
        { "cyber2000fb", cyber2000fb_init, cyber2000fb_setup },
191
#endif
192
#ifdef CONFIG_FB_PM2
193
        { "pm2fb", pm2fb_init, pm2fb_setup },
194
#endif
195
#ifdef CONFIG_FB_PM3
196
        { "pm3fb", pm3fb_init, pm3fb_setup },
197
#endif           
198
#ifdef CONFIG_FB_CLGEN
199
        { "clgenfb", clgenfb_init, clgenfb_setup },
200
#endif
201
#ifdef CONFIG_FB_ATY
202
        { "atyfb", atyfb_init, atyfb_setup },
203
#endif
204
#ifdef CONFIG_FB_MATROX
205
        { "matroxfb", matroxfb_init, matroxfb_setup },
206
#endif
207
#ifdef CONFIG_FB_ATY128
208
        { "aty128fb", aty128fb_init, aty128fb_setup },
209
#endif
210
#ifdef CONFIG_FB_NEOMAGIC
211
        { "neofb", neofb_init, neofb_setup },
212
#endif
213
#ifdef CONFIG_FB_VIRGE
214
        { "virgefb", virgefb_init, virgefb_setup },
215
#endif
216
#ifdef CONFIG_FB_RIVA
217
        { "rivafb", rivafb_init, rivafb_setup },
218
#endif
219
#ifdef CONFIG_FB_3DFX
220
        { "tdfxfb", tdfxfb_init, tdfxfb_setup },
221
#endif
222
#ifdef CONFIG_FB_RADEON
223
        { "radeonfb", radeonfb_init, radeonfb_setup },
224
#endif
225
#ifdef CONFIG_FB_CONTROL
226
        { "controlfb", control_init, control_setup },
227
#endif
228
#ifdef CONFIG_FB_PLATINUM
229
        { "platinumfb", platinum_init, platinum_setup },
230
#endif
231
#ifdef CONFIG_FB_VALKYRIE
232
        { "valkyriefb", valkyriefb_init, valkyriefb_setup },
233
#endif
234
#ifdef CONFIG_FB_CT65550
235
        { "chipsfb", chips_init, NULL },
236
#endif
237
#ifdef CONFIG_FB_IMSTT
238
        { "imsttfb", imsttfb_init, imsttfb_setup },
239
#endif
240
#ifdef CONFIG_FB_S3TRIO
241
        { "s3triofb", s3triofb_init, NULL },
242
#endif 
243
#ifdef CONFIG_FB_FM2
244
        { "fm2fb", fm2fb_init, fm2fb_setup },
245
#endif 
246
#ifdef CONFIG_FB_SIS
247
        { "sisfb", sisfb_init, sisfb_setup },
248
#endif
249
#ifdef CONFIG_FB_TRIDENT
250
        { "tridentfb", tridentfb_init, tridentfb_setup },
251
#endif
252
#ifdef CONFIG_FB_I810
253
        { "i810fb", i810fb_init, i810fb_setup },
254
#endif  
255
#ifdef CONFIG_FB_STI
256
        { "stifb", stifb_init, stifb_setup },
257
#endif
258
#ifdef CONFIG_FB_FFB
259
        { "ffb", ffb_init, ffb_setup },
260
#endif
261
#ifdef CONFIG_FB_CG6
262
        { "cg6fb", cg6_init, cg6_setup },
263
#endif
264
#ifdef CONFIG_FB_CG3
265
        { "cg3fb", cg3_init, cg3_setup },
266
#endif
267
#ifdef CONFIG_FB_BW2
268
        { "bw2fb", bw2_init, bw2_setup },
269
#endif
270
#ifdef CONFIG_FB_CG14
271
        { "cg14fb", cg14_init, cg14_setup },
272
#endif
273
#ifdef CONFIG_FB_P9100
274
        { "p9100fb", p9100_init, p9100_setup },
275
#endif
276
#ifdef CONFIG_FB_TCX
277
        { "tcxfb", tcx_init, tcx_setup },
278
#endif
279
#ifdef CONFIG_FB_LEO
280
        { "leofb", leo_init, leo_setup },
281
#endif
282
 
283
        /*
284
         * Generic drivers that are used as fallbacks
285
         *
286
         * These depend on resource management and must be initialized
287
         * _after_ all other frame buffer devices that use resource
288
         * management!
289
         */
290
 
291
#ifdef CONFIG_FB_OF
292
        { "offb", offb_init, NULL },
293
#endif
294
#ifdef CONFIG_FB_VESA
295
        { "vesafb", vesafb_init, vesafb_setup },
296
#endif 
297
 
298
        /*
299
         * Chipset specific drivers that don't use resource management (yet)
300
         */
301
 
302
#ifdef CONFIG_FB_SGIVW
303
        { "sgivwfb", sgivwfb_init, sgivwfb_setup },
304
#endif
305
#ifdef CONFIG_FB_ACORN
306
        { "acornfb", acornfb_init, acornfb_setup },
307
#endif
308
#ifdef CONFIG_FB_ATARI
309
        { "atafb", atafb_init, atafb_setup },
310
#endif
311
#ifdef CONFIG_FB_MAC
312
        { "macfb", macfb_init, macfb_setup },
313
#endif
314
#ifdef CONFIG_FB_HGA
315
        { "hgafb", hgafb_init, hgafb_setup },
316
#endif 
317
#ifdef CONFIG_FB_IGA
318
        { "igafb", igafb_init, igafb_setup },
319
#endif
320
#ifdef CONFIG_APOLLO
321
        { "apollofb", dnfb_init, NULL },
322
#endif
323
#ifdef CONFIG_FB_Q40
324
        { "q40fb", q40fb_init, NULL },
325
#endif
326
#ifdef CONFIG_FB_TGA
327
        { "tgafb", tgafb_init, tgafb_setup },
328
#endif
329
#ifdef CONFIG_FB_HP300
330
        { "hpfb", hpfb_init, NULL },
331
#endif 
332
#ifdef CONFIG_FB_G364
333
        { "g364fb", g364fb_init, NULL },
334
#endif
335
#ifdef CONFIG_FB_SA1100
336
        { "sa1100fb", sa1100fb_init, NULL },
337
#endif
338
#ifdef CONFIG_FB_SUN3
339
        { "sun3fb", sun3fb_init, sun3fb_setup },
340
#endif
341
#ifdef CONFIG_FB_HIT
342
        { "hitfb", hitfb_init, NULL },
343
#endif
344
#ifdef CONFIG_FB_TX3912
345
        { "tx3912fb", tx3912fb_init, tx3912fb_setup },
346
#endif
347
#ifdef CONFIG_FB_E1355
348
        { "e1355fb", e1355fb_init, e1355fb_setup },
349
#endif
350
#ifdef CONFIG_FB_PVR2
351
        { "pvr2fb", pvr2fb_init, pvr2fb_setup },
352
#endif
353
#ifdef CONFIG_FB_PMAG_BA
354
        { "pmagbafb", pmagbafb_init, NULL },
355
#endif          
356
#ifdef CONFIG_FB_PMAGB_B
357
        { "pmagbbfb", pmagbbfb_init, NULL },
358
#endif
359
#ifdef CONFIG_FB_MAXINE
360
        { "maxinefb", maxinefb_init, NULL },
361
#endif            
362
#ifdef CONFIG_FB_VOODOO1
363
        { "sstfb", sstfb_init, sstfb_setup },
364
#endif
365
        /*
366
         * Generic drivers that don't use resource management (yet)
367
         */
368
 
369
#ifdef CONFIG_FB_VGA16
370
        { "vga16fb", vga16fb_init, vga16fb_setup },
371
#endif 
372
 
373
#ifdef CONFIG_GSP_RESOLVER
374
        /* Not a real frame buffer device... */
375
        { "resolverfb", NULL, resolver_video_setup },
376
#endif
377
 
378
#ifdef CONFIG_FB_VIRTUAL
379
        /*
380
         * Vfb must be last to avoid that it becomes your primary display if
381
         * other display devices are present
382
         */
383
        { "vfb", vfb_init, vfb_setup },
384
#endif
385
};
386
 
387
#define NUM_FB_DRIVERS  (sizeof(fb_drivers)/sizeof(*fb_drivers))
388
#define FBPIXMAPSIZE    8192
389
 
468 giacomo 390
//extern const char *global_mode_option;
466 giacomo 391
 
392
static initcall_t pref_init_funcs[FB_MAX];
393
static int num_pref_init_funcs __initdata = 0;
394
struct fb_info *registered_fb[FB_MAX];
395
int num_registered_fb;
396
 
397
#ifdef CONFIG_FB_OF
398
static int ofonly __initdata = 0;
399
#endif
400
 
475 giacomo 401
int debx,deby,debb;
402
 
466 giacomo 403
/*
404
 * Drawing helpers.
405
 */
406
u8 sys_inbuf(u8 *src)
407
{      
408
        return *src;
409
}
410
 
411
void sys_outbuf(u8 *src, u8 *dst, unsigned int size)
412
{
413
        memcpy(dst, src, size);
414
}      
415
 
416
void move_buf_aligned(struct fb_info *info, u8 *dst, u8 *src, u32 d_pitch,
417
                        u32 s_pitch, u32 height)
418
{
419
        int i;
420
 
421
        for (i = height; i--; ) {
422
                info->pixmap.outbuf(src, dst, s_pitch);
423
                src += s_pitch;
424
                dst += d_pitch;
425
        }
426
}
427
 
428
void move_buf_unaligned(struct fb_info *info, u8 *dst, u8 *src, u32 d_pitch,
429
                        u32 height, u32 mask, u32 shift_high, u32 shift_low,
430
                        u32 mod, u32 idx)
431
{
432
        int i, j;
433
        u8 tmp;
434
 
435
        for (i = height; i--; ) {
436
                for (j = 0; j < idx; j++) {
437
                        tmp = info->pixmap.inbuf(dst+j);
438
                        tmp &= mask;
439
                        tmp |= *src >> shift_low;
440
                        info->pixmap.outbuf(&tmp, dst+j, 1);
441
                        tmp = *src << shift_high;
442
                        info->pixmap.outbuf(&tmp, dst+j+1, 1);
443
                        src++;
444
                }
445
                tmp = info->pixmap.inbuf(dst+idx);
446
                tmp &= mask;
447
                tmp |= *src >> shift_low;
448
                info->pixmap.outbuf(&tmp, dst+idx, 1);
449
                if (shift_high < mod) {
450
                        tmp = *src << shift_high;
451
                        info->pixmap.outbuf(&tmp, dst+idx+1, 1);
452
                }      
453
                src++;
454
                dst += d_pitch;
455
        }
456
}
457
 
458
/*
459
 * we need to lock this section since fb_cursor
460
 * may use fb_imageblit()
461
 */
462
u32 fb_get_buffer_offset(struct fb_info *info, u32 size)
463
{
464
        u32 align = info->pixmap.buf_align - 1;
465
        u32 offset, count = 1000;
466
 
467
        spin_lock(&info->pixmap.lock);
468
        offset = info->pixmap.offset + align;
469
        offset &= ~align;
470
        if (offset + size > info->pixmap.size) {
471
                while (atomic_read(&info->pixmap.count) && count--);
472
                if (info->fbops->fb_sync &&
473
                    info->pixmap.flags & FB_PIXMAP_SYNC)
474
                        info->fbops->fb_sync(info);
475
                offset = 0;
476
        }
477
        info->pixmap.offset = offset + size;
478
        atomic_inc(&info->pixmap.count);       
479
        smp_mb__after_atomic_inc();
480
        spin_unlock(&info->pixmap.lock);
481
        return offset;
482
}
483
 
484
#ifdef CONFIG_LOGO
485
#include <linux/linux_logo.h>
486
 
487
static inline unsigned safe_shift(unsigned d, int n)
488
{
489
        return n < 0 ? d >> -n : d << n;
490
}
491
 
492
static void __init fb_set_logocmap(struct fb_info *info,
493
                                   const struct linux_logo *logo)
494
{
495
        struct fb_cmap palette_cmap;
496
        u16 palette_green[16];
497
        u16 palette_blue[16];
498
        u16 palette_red[16];
499
        int i, j, n;
500
        const unsigned char *clut = logo->clut;
501
 
502
        palette_cmap.start = 0;
503
        palette_cmap.len = 16;
504
        palette_cmap.red = palette_red;
505
        palette_cmap.green = palette_green;
506
        palette_cmap.blue = palette_blue;
507
        palette_cmap.transp = NULL;
508
 
509
        for (i = 0; i < logo->clutsize; i += n) {
510
                n = logo->clutsize - i;
511
                /* palette_cmap provides space for only 16 colors at once */
512
                if (n > 16)
513
                        n = 16;
514
                palette_cmap.start = 32 + i;
515
                palette_cmap.len = n;
516
                for (j = 0; j < n; ++j) {
517
                        palette_cmap.red[j] = clut[0] << 8 | clut[0];
518
                        palette_cmap.green[j] = clut[1] << 8 | clut[1];
519
                        palette_cmap.blue[j] = clut[2] << 8 | clut[2];
520
                        clut += 3;
521
                }
522
                fb_set_cmap(&palette_cmap, 1, info);
523
        }
524
}
525
 
526
static void  __init fb_set_logo_truepalette(struct fb_info *info,
527
                                            const struct linux_logo *logo,
528
                                            u32 *palette)
529
{
530
        unsigned char mask[9] = { 0,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff };
531
        unsigned char redmask, greenmask, bluemask;
532
        int redshift, greenshift, blueshift;
533
        int i;
534
        const unsigned char *clut = logo->clut;
535
 
536
        /*
537
         * We have to create a temporary palette since console palette is only
538
         * 16 colors long.
539
         */
540
        /* Bug: Doesn't obey msb_right ... (who needs that?) */
541
        redmask   = mask[info->var.red.length   < 8 ? info->var.red.length   : 8];
542
        greenmask = mask[info->var.green.length < 8 ? info->var.green.length : 8];
543
        bluemask  = mask[info->var.blue.length  < 8 ? info->var.blue.length  : 8];
544
        redshift   = info->var.red.offset   - (8 - info->var.red.length);
545
        greenshift = info->var.green.offset - (8 - info->var.green.length);
546
        blueshift  = info->var.blue.offset  - (8 - info->var.blue.length);
547
 
548
        for ( i = 0; i < logo->clutsize; i++) {
549
                palette[i+32] = (safe_shift((clut[0] & redmask), redshift) |
550
                                 safe_shift((clut[1] & greenmask), greenshift) |
551
                                 safe_shift((clut[2] & bluemask), blueshift));
552
                clut += 3;
553
        }
554
}
555
 
556
static void __init fb_set_logo_directpalette(struct fb_info *info,
557
                                             const struct linux_logo *logo,
558
                                             u32 *palette)
559
{
560
        int redshift, greenshift, blueshift;
561
        int i;
562
 
563
        redshift = info->var.red.offset;
564
        greenshift = info->var.green.offset;
565
        blueshift = info->var.blue.offset;
566
 
567
        for (i = 32; i < logo->clutsize; i++)
568
                palette[i] = i << redshift | i << greenshift | i << blueshift;
569
}
570
 
571
static void __init fb_set_logo(struct fb_info *info,
572
                               const struct linux_logo *logo, u8 *dst,
573
                               int depth)
574
{
575
        int i, j, shift;
576
        const u8 *src = logo->data;
577
        u8 d, xor = 0;
578
 
579
        switch (depth) {
580
        case 4:
581
                for (i = 0; i < logo->height; i++)
582
                        for (j = 0; j < logo->width; src++) {
583
                                *dst++ = *src >> 4;
584
                                j++;
585
                                if (j < logo->width) {
586
                                        *dst++ = *src & 0x0f;
587
                                        j++;
588
                                }
589
                        }
590
                break;
591
        case ~1:
592
                xor = 0xff;
593
        case 1:
594
                for (i = 0; i < logo->height; i++) {
595
                        shift = 7;
596
                        d = *src++ ^ xor;
597
                        for (j = 0; j < logo->width; j++) {
598
                                *dst++ = (d >> shift) & 1;
599
                                shift = (shift-1) & 7;
600
                                if (shift == 7)
601
                                        d = *src++ ^ xor;
602
                        }
603
                }
604
                break;
605
        }
606
}
607
 
608
/*
609
 * Three (3) kinds of logo maps exist.  linux_logo_clut224 (>16 colors),
610
 * linux_logo_vga16 (16 colors) and linux_logo_mono (2 colors).  Depending on
611
 * the visual format and color depth of the framebuffer, the DAC, the
612
 * pseudo_palette, and the logo data will be adjusted accordingly.
613
 *
614
 * Case 1 - linux_logo_clut224:
615
 * Color exceeds the number of console colors (16), thus we set the hardware DAC
616
 * using fb_set_cmap() appropriately.  The "needs_cmapreset"  flag will be set.
617
 *
618
 * For visuals that require color info from the pseudo_palette, we also construct
619
 * one for temporary use. The "needs_directpalette" or "needs_truepalette" flags
620
 * will be set.
621
 *
622
 * Case 2 - linux_logo_vga16:
623
 * The number of colors just matches the console colors, thus there is no need
624
 * to set the DAC or the pseudo_palette.  However, the bitmap is packed, ie,
625
 * each byte contains color information for two pixels (upper and lower nibble).
626
 * To be consistent with fb_imageblit() usage, we therefore separate the two
627
 * nibbles into separate bytes. The "depth" flag will be set to 4.
628
 *
629
 * Case 3 - linux_logo_mono:
630
 * This is similar with Case 2.  Each byte contains information for 8 pixels.
631
 * We isolate each bit and expand each into a byte. The "depth" flag will
632
 * be set to 1.
633
 */
634
static struct logo_data {
635
        int depth;
636
        int needs_directpalette;
637
        int needs_truepalette;
638
        int needs_cmapreset;
639
        const struct linux_logo *logo;
640
} fb_logo;
641
 
642
int fb_prepare_logo(struct fb_info *info)
643
{
644
        memset(&fb_logo, 0, sizeof(struct logo_data));
645
 
646
        switch (info->fix.visual) {
647
        case FB_VISUAL_TRUECOLOR:
648
                if (info->var.bits_per_pixel >= 8)
649
                        fb_logo.needs_truepalette = 1;
650
                break;
651
        case FB_VISUAL_DIRECTCOLOR:
652
                if (info->var.bits_per_pixel >= 24) {
653
                        fb_logo.needs_directpalette = 1;
654
                        fb_logo.needs_cmapreset = 1;
655
                }
656
                break;
657
        case FB_VISUAL_PSEUDOCOLOR:
658
                fb_logo.needs_cmapreset = 1;
659
                break;
660
        }
661
 
662
        /* Return if no suitable logo was found */
663
        fb_logo.logo = fb_find_logo(info->var.bits_per_pixel);
664
 
665
        if (!fb_logo.logo || fb_logo.logo->height > info->var.yres) {
666
                fb_logo.logo = NULL;
667
                return 0;
668
        }
669
        /* What depth we asked for might be different from what we get */
670
        if (fb_logo.logo->type == LINUX_LOGO_CLUT224)
671
                fb_logo.depth = 8;
672
        else if (fb_logo.logo->type == LINUX_LOGO_VGA16)
673
                fb_logo.depth = 4;
674
        else
675
                fb_logo.depth = 1;             
676
        return fb_logo.logo->height;
677
}
678
 
679
int fb_show_logo(struct fb_info *info)
680
{
681
        u32 *palette = NULL, *saved_pseudo_palette = NULL;
682
        unsigned char *logo_new = NULL;
683
        struct fb_image image;
684
        int x;
685
 
686
        /* Return if the frame buffer is not mapped */
687
        if (fb_logo.logo == NULL)
688
                return 0;
689
 
690
        image.depth = fb_logo.depth;
691
        image.data = fb_logo.logo->data;
692
 
693
        if (fb_logo.needs_cmapreset)
694
                fb_set_logocmap(info, fb_logo.logo);
695
 
696
        if (fb_logo.needs_truepalette ||
697
            fb_logo.needs_directpalette) {
698
                palette = kmalloc(256 * 4, GFP_KERNEL);
699
                if (palette == NULL)
700
                        return 0;
701
 
702
                if (fb_logo.needs_truepalette)
703
                        fb_set_logo_truepalette(info, fb_logo.logo, palette);
704
                else
705
                        fb_set_logo_directpalette(info, fb_logo.logo, palette);
706
 
707
                saved_pseudo_palette = info->pseudo_palette;
708
                info->pseudo_palette = palette;
709
        }
710
 
711
        if (fb_logo.depth == 4) {
712
                logo_new = kmalloc(fb_logo.logo->width * fb_logo.logo->height,
713
                                   GFP_KERNEL);
714
                if (logo_new == NULL) {
715
                        if (palette)
716
                                kfree(palette);
717
                        if (saved_pseudo_palette)
718
                                info->pseudo_palette = saved_pseudo_palette;
719
                        return 0;
720
                }
721
                image.data = logo_new;
722
                fb_set_logo(info, fb_logo.logo, logo_new, fb_logo.depth);
723
        }
724
 
725
        image.width = fb_logo.logo->width;
726
        image.height = fb_logo.logo->height;
727
        image.dy = 0;
728
 
729
        for (x = 0; x < num_online_cpus() * (fb_logo.logo->width + 8) &&
730
             x <= info->var.xres-fb_logo.logo->width; x += (fb_logo.logo->width + 8)) {
731
                image.dx = x;
732
                info->fbops->fb_imageblit(info, &image);
733
                //atomic_dec(&info->pixmap.count);
734
                //smp_mb__after_atomic_dec();
735
        }
736
 
737
        if (palette != NULL)
738
                kfree(palette);
739
        if (saved_pseudo_palette != NULL)
740
                info->pseudo_palette = saved_pseudo_palette;
741
        if (logo_new != NULL)
742
                kfree(logo_new);
743
        return fb_logo.logo->height;
744
}
745
#else
746
int fb_prepare_logo(struct fb_info *info) { return 0; }
747
int fb_show_logo(struct fb_info *info) { return 0; }
748
#endif /* CONFIG_LOGO */
749
 
750
static int fbmem_read_proc(char *buf, char **start, off_t offset,
751
                           int len, int *eof, void *private)
752
{
753
        struct fb_info **fi;
754
        int clen;
755
 
756
        clen = 0;
757
        for (fi = registered_fb; fi < &registered_fb[FB_MAX] && len < 4000; fi++)
758
                if (*fi)
759
                        clen += sprintf26(buf + clen, "%d %s\n",
760
                                        (*fi)->node,
761
                                        (*fi)->fix.id);
762
        *start = buf + offset;
763
        if (clen > offset)
764
                clen -= offset;
765
        else
766
                clen = 0;
767
        return clen < len ? clen : len;
768
}
769
 
770
static ssize_t
771
fb_read(struct file *file, char *buf, size_t count, loff_t *ppos)
772
{
773
        unsigned long p = *ppos;
774
        struct inode *inode = file->f_dentry->d_inode;
775
        int fbidx = iminor(inode);
776
        struct fb_info *info = registered_fb[fbidx];
777
 
778
        if (!info || ! info->screen_base)
779
                return -ENODEV;
780
 
781
        if (info->fbops->fb_read)
782
                return info->fbops->fb_read(file, buf, count, ppos);
783
 
784
        if (p >= info->fix.smem_len)
785
            return 0;
786
        if (count >= info->fix.smem_len)
787
            count = info->fix.smem_len;
788
        if (count + p > info->fix.smem_len)
789
                count = info->fix.smem_len - p;
790
        if (info->fbops->fb_sync)
791
                info->fbops->fb_sync(info);
792
        if (count) {
793
            char *base_addr;
794
 
795
            base_addr = info->screen_base;
796
            count -= copy_to_user(buf, base_addr+p, count);
797
            if (!count)
798
                return -EFAULT;
799
            *ppos += count;
800
        }
801
        return count;
802
}
803
 
804
static ssize_t
805
fb_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
806
{
807
        unsigned long p = *ppos;
808
        struct inode *inode = file->f_dentry->d_inode;
809
        int fbidx = iminor(inode);
810
        struct fb_info *info = registered_fb[fbidx];
811
        int err;
812
 
813
        if (!info || !info->screen_base)
814
                return -ENODEV;
815
 
816
        if (info->fbops->fb_write)
817
                return info->fbops->fb_write(file, buf, count, ppos);
818
 
819
        if (p > info->fix.smem_len)
820
            return -ENOSPC;
821
        if (count >= info->fix.smem_len)
822
            count = info->fix.smem_len;
823
        err = 0;
824
        if (count + p > info->fix.smem_len) {
825
            count = info->fix.smem_len - p;
826
            err = -ENOSPC;
827
        }
828
        if (info->fbops->fb_sync)
829
                info->fbops->fb_sync(info);
830
        if (count) {
831
            char *base_addr;
832
 
833
            base_addr = info->screen_base;
834
            count -= copy_from_user(base_addr+p, buf, count);
835
            *ppos += count;
836
            err = -EFAULT;
837
        }
838
        if (count)
839
                return count;
840
        return err;
841
}
842
 
843
#ifdef CONFIG_KMOD
844
static void try_to_load(int fb)
845
{
846
        request_module("fb%d", fb);
847
}
848
#endif /* CONFIG_KMOD */
849
 
850
int
851
fb_cursor(struct fb_info *info, struct fb_cursor *sprite)
852
{
853
        struct fb_cursor cursor;
854
        int err;
855
 
856
        if (copy_from_user(&cursor, sprite, sizeof(struct fb_cursor)))
857
                return -EFAULT;
858
 
859
        if (cursor.set & FB_CUR_SETCUR)
860
                info->cursor.enable = 1;
861
 
862
        if (cursor.set & FB_CUR_SETCMAP) {
863
                err = fb_copy_cmap(&cursor.image.cmap, &sprite->image.cmap, 1);
864
                if (err)
865
                        return err;
866
        }
867
 
868
        if (cursor.set & FB_CUR_SETSHAPE) {
869
                int size = ((cursor.image.width + 7) >> 3) * cursor.image.height;              
870
                if ((cursor.image.height != info->cursor.image.height) ||
871
                    (cursor.image.width != info->cursor.image.width))
872
                        cursor.set |= FB_CUR_SETSIZE;
873
 
874
                cursor.image.data = kmalloc(size, GFP_KERNEL);
875
                if (!cursor.image.data)
876
                        return -ENOMEM;
877
 
878
                cursor.mask = kmalloc(size, GFP_KERNEL);
879
                if (!cursor.mask) {
880
                        kfree(cursor.image.data);
881
                        return -ENOMEM;
882
                }
883
 
884
                if (copy_from_user(&cursor.image.data, sprite->image.data, size) ||
885
                    copy_from_user(cursor.mask, sprite->mask, size)) {
886
                        kfree(cursor.image.data);
887
                        kfree(cursor.mask);
888
                        return -EFAULT;
889
                }
890
        }
891
        info->cursor.set = cursor.set;
892
        info->cursor.rop = cursor.rop;
893
        err = info->fbops->fb_cursor(info, &cursor);
894
        return err;
895
}
896
 
897
int
898
fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var)
899
{
900
        int xoffset = var->xoffset;
901
        int yoffset = var->yoffset;
902
        int err;
903
 
904
        if (xoffset < 0 || yoffset < 0 || !info->fbops->fb_pan_display ||
905
            xoffset + info->var.xres > info->var.xres_virtual ||
906
            yoffset + info->var.yres > info->var.yres_virtual)
907
                return -EINVAL;
908
        if ((err = info->fbops->fb_pan_display(var, info)))
909
                return err;
910
        info->var.xoffset = var->xoffset;
911
        info->var.yoffset = var->yoffset;
912
        if (var->vmode & FB_VMODE_YWRAP)
913
                info->var.vmode |= FB_VMODE_YWRAP;
914
        else
915
                info->var.vmode &= ~FB_VMODE_YWRAP;
916
        return 0;
917
}
918
 
919
int
920
fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
921
{
922
        int err;
923
 
924
        if (memcmp(&info->var, var, sizeof(struct fb_var_screeninfo))) {
925
                if (!info->fbops->fb_check_var) {
926
                        *var = info->var;
927
                        return 0;
928
                }
929
 
930
                if ((err = info->fbops->fb_check_var(var, info)))
931
                        return err;
932
 
933
                if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
934
                        info->var = *var;
935
 
936
                        if (info->fbops->fb_set_par)
937
                                info->fbops->fb_set_par(info);
938
 
939
                        fb_pan_display(info, &info->var);
940
 
941
                        fb_set_cmap(&info->cmap, 1, info);
942
                }
943
        }
944
        return 0;
945
}
946
 
947
int
948
fb_blank(struct fb_info *info, int blank)
949
{      
950
        /* ??? Variable sized stack allocation.  */
951
        u16 black[info->cmap.len];
952
        struct fb_cmap cmap;
953
 
954
        if (info->fbops->fb_blank && !info->fbops->fb_blank(blank, info))
955
                return 0;
956
        if (blank) {
957
                memset(black, 0, info->cmap.len * sizeof(u16));
958
                cmap.red = cmap.green = cmap.blue = black;
959
                cmap.transp = info->cmap.transp ? black : NULL;
960
                cmap.start = info->cmap.start;
961
                cmap.len = info->cmap.len;
962
        } else
963
                cmap = info->cmap;
964
        return fb_set_cmap(&cmap, 1, info);
965
}
966
 
472 giacomo 967
int
466 giacomo 968
fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
969
         unsigned long arg)
970
{
971
        int fbidx = iminor(inode);
972
        struct fb_info *info = registered_fb[fbidx];
973
        struct fb_ops *fb = info->fbops;
974
        struct fb_var_screeninfo var;
975
        struct fb_fix_screeninfo fix;
976
#ifdef CONFIG_FRAMEBUFFER_CONSOLE
977
        struct fb_con2fbmap con2fb;
978
#endif
979
        struct fb_cmap cmap;
980
        int i;
981
 
982
        if (!fb)
983
                return -ENODEV;
984
        switch (cmd) {
985
        case FBIOGET_VSCREENINFO:
986
                return copy_to_user((void *) arg, &info->var,
987
                                    sizeof(var)) ? -EFAULT : 0;
988
        case FBIOPUT_VSCREENINFO:
989
                if (copy_from_user(&var, (void *) arg, sizeof(var)))
990
                        return -EFAULT;
991
                i = fb_set_var(info, &var);
992
                if (i) return i;
993
                if (copy_to_user((void *) arg, &var, sizeof(var)))
994
                        return -EFAULT;
995
                return 0;
996
        case FBIOGET_FSCREENINFO:
997
                return copy_to_user((void *) arg, &info->fix,
998
                                    sizeof(fix)) ? -EFAULT : 0;
999
        case FBIOPUTCMAP:
1000
                if (copy_from_user(&cmap, (void *) arg, sizeof(cmap)))
1001
                        return -EFAULT;
1002
                return (fb_set_cmap(&cmap, 0, info));
1003
        case FBIOGETCMAP:
1004
                if (copy_from_user(&cmap, (void *) arg, sizeof(cmap)))
1005
                        return -EFAULT;
1006
                return (fb_copy_cmap(&info->cmap, &cmap, 0));
1007
        case FBIOPAN_DISPLAY:
1008
                if (copy_from_user(&var, (void *) arg, sizeof(var)))
1009
                        return -EFAULT;
1010
                if ((i = fb_pan_display(info, &var)))
1011
                        return i;
1012
                if (copy_to_user((void *) arg, &var, sizeof(var)))
1013
                        return -EFAULT;
1014
                return 0;
1015
        case FBIO_CURSOR:
1016
                return (fb_cursor(info, (struct fb_cursor *) arg));
1017
#ifdef CONFIG_FRAMEBUFFER_CONSOLE
1018
        case FBIOGET_CON2FBMAP:
1019
                if (copy_from_user(&con2fb, (void *)arg, sizeof(con2fb)))
1020
                        return -EFAULT;
1021
                if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)
1022
                    return -EINVAL;
1023
                con2fb.framebuffer = con2fb_map[con2fb.console-1];
1024
                return copy_to_user((void *)arg, &con2fb,
1025
                                    sizeof(con2fb)) ? -EFAULT : 0;
1026
        case FBIOPUT_CON2FBMAP:
1027
                if (copy_from_user(&con2fb, (void *)arg, sizeof(con2fb)))
1028
                        return - EFAULT;
1029
                if (con2fb.console < 0 || con2fb.console > MAX_NR_CONSOLES)
1030
                    return -EINVAL;
1031
                if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX)
1032
                    return -EINVAL;
1033
#ifdef CONFIG_KMOD
1034
                if (!registered_fb[con2fb.framebuffer])
1035
                    try_to_load(con2fb.framebuffer);
1036
#endif /* CONFIG_KMOD */
1037
                if (!registered_fb[con2fb.framebuffer])
1038
                    return -EINVAL;
1039
                if (con2fb.console != 0)
1040
                        set_con2fb_map(con2fb.console-1, con2fb.framebuffer);
1041
                else
1042
                        fb_console_init();             
1043
                return 0;
1044
#endif  /* CONFIG_FRAMEBUFFER_CONSOLE */
1045
        case FBIOBLANK:
1046
                return fb_blank(info, arg);
1047
        default:
1048
                if (fb->fb_ioctl == NULL)
1049
                        return -EINVAL;
1050
                return fb->fb_ioctl(inode, file, cmd, arg, info);
1051
        }
1052
}
1053
 
1054
static int
1055
fb_mmap(struct file *file, struct vm_area_struct * vma)
1056
{
1057
        int fbidx = iminor(file->f_dentry->d_inode);
1058
        struct fb_info *info = registered_fb[fbidx];
1059
        struct fb_ops *fb = info->fbops;
1060
        unsigned long off;
1061
#if !defined(__sparc__) || defined(__sparc_v9__)
1062
        unsigned long start;
1063
        u32 len;
1064
#endif
1065
 
1066
        if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
1067
                return -EINVAL;
1068
        off = vma->vm_pgoff << PAGE_SHIFT;
1069
        if (!fb)
1070
                return -ENODEV;
1071
        if (fb->fb_mmap) {
1072
                int res;
1073
                lock_kernel();
1074
                res = fb->fb_mmap(info, file, vma);
1075
                unlock_kernel();
1076
                return res;
1077
        }
1078
 
1079
#if defined(__sparc__) && !defined(__sparc_v9__)
1080
        /* Should never get here, all fb drivers should have their own
1081
           mmap routines */
1082
        return -EINVAL;
1083
#else
1084
        /* !sparc32... */
1085
        lock_kernel();
1086
 
1087
        /* frame buffer memory */
1088
        start = info->fix.smem_start;
1089
        len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len);
1090
        if (off >= len) {
1091
                /* memory mapped io */
1092
                off -= len;
1093
                if (info->var.accel_flags) {
1094
                        unlock_kernel();
1095
                        return -EINVAL;
1096
                }
1097
                start = info->fix.mmio_start;
1098
                len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len);
1099
        }
1100
        unlock_kernel();
1101
        start &= PAGE_MASK;
1102
        if ((vma->vm_end - vma->vm_start + off) > len)
1103
                return -EINVAL;
1104
        off += start;
1105
        vma->vm_pgoff = off >> PAGE_SHIFT;
1106
        /* This is an IO map - tell maydump to skip this VMA */
1107
        vma->vm_flags |= VM_IO;
1108
#if defined(__sparc_v9__)
1109
        vma->vm_flags |= (VM_SHM | VM_LOCKED);
1110
        if (io_remap_page_range(vma, vma->vm_start, off,
1111
                                vma->vm_end - vma->vm_start, vma->vm_page_prot, 0))
1112
                return -EAGAIN;
1113
#else
1114
#if defined(__mc68000__)
1115
#if defined(CONFIG_SUN3)
1116
        pgprot_val(vma->vm_page_prot) |= SUN3_PAGE_NOCACHE;
1117
#elif defined(CONFIG_MMU)
1118
        if (CPU_IS_020_OR_030)
1119
                pgprot_val(vma->vm_page_prot) |= _PAGE_NOCACHE030;
1120
        if (CPU_IS_040_OR_060) {
1121
                pgprot_val(vma->vm_page_prot) &= _CACHEMASK040;
1122
                /* Use no-cache mode, serialized */
1123
                pgprot_val(vma->vm_page_prot) |= _PAGE_NOCACHE_S;
1124
        }
1125
#endif
1126
#elif defined(__powerpc__)
1127
        pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE|_PAGE_GUARDED;
1128
#elif defined(__alpha__)
1129
        /* Caching is off in the I/O space quadrant by design.  */
1130
#elif defined(__i386__) || defined(__x86_64__)
468 giacomo 1131
        //if (boot_cpu_data.x86 > 3)
1132
        //      pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
466 giacomo 1133
#elif defined(__mips__)
1134
        pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK;
1135
        pgprot_val(vma->vm_page_prot) |= _CACHE_UNCACHED;
1136
#elif defined(__sh__)
1137
        pgprot_val(vma->vm_page_prot) &= ~_PAGE_CACHABLE;
1138
#elif defined(__hppa__)
1139
        pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
1140
#elif defined(__ia64__) || defined(__arm__)
1141
        vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
1142
#else
1143
#warning What do we have to do here??
1144
#endif
1145
        if (io_remap_page_range(vma, vma->vm_start, off,
1146
                             vma->vm_end - vma->vm_start, vma->vm_page_prot))
1147
                return -EAGAIN;
1148
#endif /* !__sparc_v9__ */
1149
        return 0;
1150
#endif /* !sparc32 */
1151
}
1152
 
470 giacomo 1153
static int
466 giacomo 1154
fb_open(struct inode *inode, struct file *file)
1155
{
1156
        int fbidx = iminor(inode);
1157
        struct fb_info *info;
475 giacomo 1158
        int res = 0,i;
466 giacomo 1159
 
1160
        if (fbidx >= FB_MAX)
1161
                return -ENODEV;
1162
#ifdef CONFIG_KMOD
1163
        if (!(info = registered_fb[fbidx]))
1164
                try_to_load(fbidx);
1165
#endif /* CONFIG_KMOD */
1166
        if (!(info = registered_fb[fbidx]))
1167
                return -ENODEV;
1168
        if (!try_module_get(info->fbops->owner))
1169
                return -ENODEV;
1170
        if (info->fbops->fb_open) {
1171
                res = info->fbops->fb_open(info,1);
1172
                if (res)
1173
                        module_put(info->fbops->owner);
1174
        }
475 giacomo 1175
 
1176
        debx = info->var.xres;
1177
        deby = info->var.yres;
1178
        debb = info->fix.smem_start;
1179
        for (i=0;i<639;i++) *(unsigned char *)(info->fix.smem_start+i) = 0x55;
1180
 
466 giacomo 1181
        return res;
1182
}
1183
 
470 giacomo 1184
static int
466 giacomo 1185
fb_release(struct inode *inode, struct file *file)
1186
{
1187
        int fbidx = iminor(inode);
1188
        struct fb_info *info;
1189
 
1190
        lock_kernel();
1191
        info = registered_fb[fbidx];
1192
        if (info->fbops->fb_release)
1193
                info->fbops->fb_release(info,1);
1194
        module_put(info->fbops->owner);
1195
        unlock_kernel();
475 giacomo 1196
 
1197
        cprintf("X %d Y %d B %x\n",debx,deby,debb);
1198
 
466 giacomo 1199
        return 0;
1200
}
1201
 
1202
static struct file_operations fb_fops = {
1203
        .owner =        THIS_MODULE,
1204
        .read =         fb_read,
1205
        .write =        fb_write,
1206
        .ioctl =        fb_ioctl,
1207
        .mmap =         fb_mmap,
1208
        .open =         fb_open,
1209
        .release =      fb_release,
1210
#ifdef HAVE_ARCH_FB_UNMAPPED_AREA
1211
        .get_unmapped_area = get_fb_unmapped_area,
1212
#endif
1213
};
1214
 
1215
/**
1216
 *      register_framebuffer - registers a frame buffer device
1217
 *      @fb_info: frame buffer info structure
1218
 *
1219
 *      Registers a frame buffer device @fb_info.
1220
 *
1221
 *      Returns negative errno on error, or zero for success.
1222
 *
1223
 */
1224
 
1225
int
1226
register_framebuffer(struct fb_info *fb_info)
1227
{
1228
        int i;
1229
 
1230
        if (num_registered_fb == FB_MAX)
1231
                return -ENXIO;
1232
        num_registered_fb++;
1233
        for (i = 0 ; i < FB_MAX; i++)
1234
                if (!registered_fb[i])
1235
                        break;
1236
        fb_info->node = i;
1237
 
1238
        if (fb_info->pixmap.addr == NULL) {
1239
                fb_info->pixmap.addr = kmalloc(FBPIXMAPSIZE, GFP_KERNEL);
1240
                if (fb_info->pixmap.addr) {
1241
                        fb_info->pixmap.size = FBPIXMAPSIZE;
1242
                        fb_info->pixmap.buf_align = 1;
1243
                        fb_info->pixmap.scan_align = 1;
1244
                        fb_info->pixmap.flags = FB_PIXMAP_DEFAULT;
1245
                }
1246
        }      
1247
        fb_info->pixmap.offset = 0;
1248
        if (fb_info->pixmap.outbuf == NULL)
1249
                fb_info->pixmap.outbuf = sys_outbuf;
1250
        if (fb_info->pixmap.inbuf == NULL)
1251
                fb_info->pixmap.inbuf = sys_inbuf;
1252
        spin_lock_init(&fb_info->pixmap.lock);
1253
 
1254
        registered_fb[i] = fb_info;
1255
 
1256
        devfs_mk_cdev(MKDEV(FB_MAJOR, i),
1257
                        S_IFCHR | S_IRUGO | S_IWUGO, "fb/%d", i);
1258
        return 0;
1259
}
1260
 
1261
 
1262
/**
1263
 *      unregister_framebuffer - releases a frame buffer device
1264
 *      @fb_info: frame buffer info structure
1265
 *
1266
 *      Unregisters a frame buffer device @fb_info.
1267
 *
1268
 *      Returns negative errno on error, or zero for success.
1269
 *
1270
 */
1271
 
1272
int
1273
unregister_framebuffer(struct fb_info *fb_info)
1274
{
1275
        int i;
1276
 
1277
        i = fb_info->node;
1278
        if (!registered_fb[i])
1279
                return -EINVAL;
1280
        devfs_remove("fb/%d", i);
1281
 
1282
        if (fb_info->pixmap.addr)
1283
                kfree(fb_info->pixmap.addr);
1284
        registered_fb[i]=NULL;
1285
        num_registered_fb--;
1286
        return 0;
1287
}
1288
 
1289
 
1290
/**
1291
 *      fbmem_init - init frame buffer subsystem
1292
 *
1293
 *      Initialize the frame buffer subsystem.
1294
 *
1295
 *      NOTE: This function is _only_ to be called by drivers/char/mem.c.
1296
 *
1297
 */
1298
 
1299
void __init
1300
fbmem_init(void)
1301
{
1302
        int i;
1303
 
1304
        create_proc_read_entry("fb", 0, 0, fbmem_read_proc, NULL);
1305
 
1306
        devfs_mk_dir("fb");
1307
        if (register_chrdev(FB_MAJOR,"fb",&fb_fops))
1308
                printk("unable to get major %d for fb devs\n", FB_MAJOR);
1309
 
1310
#ifdef CONFIG_FB_OF
1311
        if (ofonly) {
1312
                offb_init();
1313
                return;
1314
        }
1315
#endif
1316
 
1317
        /*
1318
         *  Probe for all builtin frame buffer devices
1319
         */
1320
        for (i = 0; i < num_pref_init_funcs; i++)
1321
                pref_init_funcs[i]();
1322
 
1323
        for (i = 0; i < NUM_FB_DRIVERS; i++)
1324
                if (fb_drivers[i].init)
1325
                        fb_drivers[i].init();
1326
}
1327
 
469 giacomo 1328
extern int linuxcomp_setfd(struct inode *i, int i_rdev);
466 giacomo 1329
 
469 giacomo 1330
/* Shark Inode emulation */
1331
int fb_open_inode(int num) {
470 giacomo 1332
 
1333
  struct inode *i;
1334
 
1335
  i = (struct inode *)kmalloc(sizeof(struct inode),GFP_KERNEL);
1336
 
1337
  linuxcomp_setfd(i,num);
1338
 
472 giacomo 1339
  if (fb_open(i,NULL)) {
1340
    kfree(i);
1341
    return -1;
1342
  }
469 giacomo 1343
 
475 giacomo 1344
  kfree(i);                                                                                                            
470 giacomo 1345
  return 0;
1346
 
1347
}
1348
 
1349
/* Shark Inode emulation */
1350
int fb_close_inode(int num) {
1351
 
469 giacomo 1352
  struct inode *i;
1353
 
1354
  i = (struct inode *)kmalloc(sizeof(struct inode),GFP_KERNEL);
1355
 
1356
  linuxcomp_setfd(i,num);
1357
 
472 giacomo 1358
  if(fb_release(i,NULL)) {
1359
    kfree(i);
1360
    return -1;
1361
  }
469 giacomo 1362
 
470 giacomo 1363
  kfree(i);
1364
 
469 giacomo 1365
  return 0;
1366
 
1367
}
1368
 
472 giacomo 1369
int fb_set_mode_inode(int num, int wx, int wy, int bpp) {
1370
 
1371
  struct inode *i;
1372
  struct fb_var_screeninfo var;
1373
 
1374
  i = (struct inode *)kmalloc(sizeof(struct inode),GFP_KERNEL);
1375
 
1376
  linuxcomp_setfd(i,num);
1377
 
1378
  if (fb_ioctl(i, NULL, FBIOGET_VSCREENINFO, (unsigned long)&var)) {
1379
    kfree(i);
1380
    return -1;
1381
  }
1382
 
1383
  var.xres = wx;
1384
  var.yres = wy;
1385
  var.xres_virtual = wx;
1386
  var.yres_virtual = wy;
1387
  var.xoffset = 0;
1388
  var.yoffset = 0;
1389
  var.bits_per_pixel = bpp;
1390
 
1391
  if (fb_ioctl(i, NULL, FBIOPUT_VSCREENINFO, (unsigned long)&var)) {
1392
    kfree(i);
1393
    return -1;
1394
  }
1395
 
1396
  kfree(i);
1397
 
1398
  return 0;
1399
 
1400
}
1401
 
466 giacomo 1402
/**
1403
 *      video_setup - process command line options
1404
 *      @options: string of options
1405
 *
1406
 *      Process command line options for frame buffer subsystem.
1407
 *
1408
 *      NOTE: This function is a __setup and __init function.
1409
 *
1410
 *      Returns zero.
1411
 *
1412
 */
1413
 
1414
int __init video_setup(char *options)
1415
{
1416
        int i, j;
1417
 
1418
        if (!options || !*options)
1419
                return 0;
1420
 
1421
#ifdef CONFIG_FB_OF
1422
        if (!strcmp(options, "ofonly")) {
1423
                ofonly = 1;
1424
                return 0;
1425
        }
1426
#endif
1427
 
1428
        if (num_pref_init_funcs == FB_MAX)
1429
                return 0;
1430
 
1431
        for (i = 0; i < NUM_FB_DRIVERS; i++) {
1432
                j = strlen(fb_drivers[i].name);
1433
                if (!strncmp(options, fb_drivers[i].name, j) &&
1434
                        options[j] == ':') {
1435
                        if (!strcmp(options+j+1, "off"))
1436
                                fb_drivers[i].init = NULL;
1437
                        else {
1438
                                if (fb_drivers[i].init) {
1439
                                        pref_init_funcs[num_pref_init_funcs++] =
1440
                                                fb_drivers[i].init;
1441
                                        fb_drivers[i].init = NULL;
1442
                                }
1443
                                if (fb_drivers[i].setup)
1444
                                        fb_drivers[i].setup(options+j+1);
1445
                        }
1446
                        return 0;
1447
                }
1448
        }
1449
 
1450
        /*
1451
         * If we get here no fb was specified.
1452
         * We consider the argument to be a global video mode option.
1453
         */
468 giacomo 1454
        //global_mode_option = options;
466 giacomo 1455
        return 0;
1456
}
1457
 
1458
__setup("video=", video_setup);
1459
 
1460
    /*
1461
     *  Visible symbols for modules
1462
     */
1463
 
1464
EXPORT_SYMBOL(register_framebuffer);
1465
EXPORT_SYMBOL(unregister_framebuffer);
1466
EXPORT_SYMBOL(num_registered_fb);
1467
EXPORT_SYMBOL(registered_fb);
1468
EXPORT_SYMBOL(fb_prepare_logo);
1469
EXPORT_SYMBOL(fb_show_logo);
1470
EXPORT_SYMBOL(fb_set_var);
1471
EXPORT_SYMBOL(fb_blank);
1472
EXPORT_SYMBOL(fb_pan_display);
1473
EXPORT_SYMBOL(fb_get_buffer_offset);
1474
EXPORT_SYMBOL(move_buf_unaligned);
1475
EXPORT_SYMBOL(move_buf_aligned);
1476
 
1477
MODULE_LICENSE("GPL");