Subversion Repositories shark

Rev

Rev 489 | 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
 
401
/*
402
 * Drawing helpers.
403
 */
404
u8 sys_inbuf(u8 *src)
405
{
406
	return *src;
407
}
408
 
409
void sys_outbuf(u8 *src, u8 *dst, unsigned int size)
410
{
411
	memcpy(dst, src, size);
412
}
413
 
414
void move_buf_aligned(struct fb_info *info, u8 *dst, u8 *src, u32 d_pitch,
415
			u32 s_pitch, u32 height)
416
{
417
	int i;
418
 
419
	for (i = height; i--; ) {
420
		info->pixmap.outbuf(src, dst, s_pitch);
421
		src += s_pitch;
422
		dst += d_pitch;
423
	}
424
}
425
 
426
void move_buf_unaligned(struct fb_info *info, u8 *dst, u8 *src, u32 d_pitch,
427
			u32 height, u32 mask, u32 shift_high, u32 shift_low,
428
			u32 mod, u32 idx)
429
{
430
	int i, j;
431
	u8 tmp;
432
 
433
	for (i = height; i--; ) {
434
		for (j = 0; j < idx; j++) {
435
			tmp = info->pixmap.inbuf(dst+j);
436
			tmp &= mask;
437
			tmp |= *src >> shift_low;
438
			info->pixmap.outbuf(&tmp, dst+j, 1);
439
			tmp = *src << shift_high;
440
			info->pixmap.outbuf(&tmp, dst+j+1, 1);
441
			src++;
442
		}
443
		tmp = info->pixmap.inbuf(dst+idx);
444
		tmp &= mask;
445
		tmp |= *src >> shift_low;
446
		info->pixmap.outbuf(&tmp, dst+idx, 1);
447
		if (shift_high < mod) {
448
			tmp = *src << shift_high;
449
			info->pixmap.outbuf(&tmp, dst+idx+1, 1);
450
		}
451
		src++;
452
		dst += d_pitch;
453
	}
454
}
455
 
456
/*
457
 * we need to lock this section since fb_cursor
458
 * may use fb_imageblit()
459
 */
460
u32 fb_get_buffer_offset(struct fb_info *info, u32 size)
461
{
462
	u32 align = info->pixmap.buf_align - 1;
463
	u32 offset, count = 1000;
464
 
465
	spin_lock(&info->pixmap.lock);
466
	offset = info->pixmap.offset + align;
467
	offset &= ~align;
468
	if (offset + size > info->pixmap.size) {
469
		while (atomic_read(&info->pixmap.count) && count--);
470
		if (info->fbops->fb_sync &&
471
		    info->pixmap.flags & FB_PIXMAP_SYNC)
472
			info->fbops->fb_sync(info);
473
		offset = 0;
474
	}
475
	info->pixmap.offset = offset + size;
476
	atomic_inc(&info->pixmap.count);
477
	smp_mb__after_atomic_inc();
478
	spin_unlock(&info->pixmap.lock);
479
	return offset;
480
}
481
 
482
#ifdef CONFIG_LOGO
483
#include <linux/linux_logo.h>
484
 
485
static inline unsigned safe_shift(unsigned d, int n)
486
{
487
	return n < 0 ? d >> -n : d << n;
488
}
489
 
490
static void __init fb_set_logocmap(struct fb_info *info,
491
				   const struct linux_logo *logo)
492
{
493
	struct fb_cmap palette_cmap;
494
	u16 palette_green[16];
495
	u16 palette_blue[16];
496
	u16 palette_red[16];
497
	int i, j, n;
498
	const unsigned char *clut = logo->clut;
499
 
500
	palette_cmap.start = 0;
501
	palette_cmap.len = 16;
502
	palette_cmap.red = palette_red;
503
	palette_cmap.green = palette_green;
504
	palette_cmap.blue = palette_blue;
505
	palette_cmap.transp = NULL;
506
 
507
	for (i = 0; i < logo->clutsize; i += n) {
508
		n = logo->clutsize - i;
509
		/* palette_cmap provides space for only 16 colors at once */
510
		if (n > 16)
511
			n = 16;
512
		palette_cmap.start = 32 + i;
513
		palette_cmap.len = n;
514
		for (j = 0; j < n; ++j) {
515
			palette_cmap.red[j] = clut[0] << 8 | clut[0];
516
			palette_cmap.green[j] = clut[1] << 8 | clut[1];
517
			palette_cmap.blue[j] = clut[2] << 8 | clut[2];
518
			clut += 3;
519
		}
520
		fb_set_cmap(&palette_cmap, 1, info);
521
	}
522
}
523
 
524
static void  __init fb_set_logo_truepalette(struct fb_info *info,
525
					    const struct linux_logo *logo,
526
					    u32 *palette)
527
{
528
	unsigned char mask[9] = { 0,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff };
529
	unsigned char redmask, greenmask, bluemask;
530
	int redshift, greenshift, blueshift;
531
	int i;
532
	const unsigned char *clut = logo->clut;
533
 
534
	/*
535
	 * We have to create a temporary palette since console palette is only
536
	 * 16 colors long.
537
	 */
538
	/* Bug: Doesn't obey msb_right ... (who needs that?) */
539
	redmask   = mask[info->var.red.length   < 8 ? info->var.red.length   : 8];
540
	greenmask = mask[info->var.green.length < 8 ? info->var.green.length : 8];
541
	bluemask  = mask[info->var.blue.length  < 8 ? info->var.blue.length  : 8];
542
	redshift   = info->var.red.offset   - (8 - info->var.red.length);
543
	greenshift = info->var.green.offset - (8 - info->var.green.length);
544
	blueshift  = info->var.blue.offset  - (8 - info->var.blue.length);
545
 
546
	for ( i = 0; i < logo->clutsize; i++) {
547
		palette[i+32] = (safe_shift((clut[0] & redmask), redshift) |
548
				 safe_shift((clut[1] & greenmask), greenshift) |
549
				 safe_shift((clut[2] & bluemask), blueshift));
550
		clut += 3;
551
	}
552
}
553
 
554
static void __init fb_set_logo_directpalette(struct fb_info *info,
555
					     const struct linux_logo *logo,
556
					     u32 *palette)
557
{
558
	int redshift, greenshift, blueshift;
559
	int i;
560
 
561
	redshift = info->var.red.offset;
562
	greenshift = info->var.green.offset;
563
	blueshift = info->var.blue.offset;
564
 
565
	for (i = 32; i < logo->clutsize; i++)
566
		palette[i] = i << redshift | i << greenshift | i << blueshift;
567
}
568
 
569
static void __init fb_set_logo(struct fb_info *info,
570
			       const struct linux_logo *logo, u8 *dst,
571
			       int depth)
572
{
573
	int i, j, shift;
574
	const u8 *src = logo->data;
575
	u8 d, xor = 0;
576
 
577
	switch (depth) {
578
	case 4:
579
		for (i = 0; i < logo->height; i++)
580
			for (j = 0; j < logo->width; src++) {
581
				*dst++ = *src >> 4;
582
				j++;
583
				if (j < logo->width) {
584
					*dst++ = *src & 0x0f;
585
					j++;
586
				}
587
			}
588
		break;
589
	case ~1:
590
		xor = 0xff;
591
	case 1:
592
		for (i = 0; i < logo->height; i++) {
593
			shift = 7;
594
			d = *src++ ^ xor;
595
			for (j = 0; j < logo->width; j++) {
596
				*dst++ = (d >> shift) & 1;
597
				shift = (shift-1) & 7;
598
				if (shift == 7)
599
					d = *src++ ^ xor;
600
			}
601
		}
602
		break;
603
	}
604
}
605
 
606
/*
607
 * Three (3) kinds of logo maps exist.  linux_logo_clut224 (>16 colors),
608
 * linux_logo_vga16 (16 colors) and linux_logo_mono (2 colors).  Depending on
609
 * the visual format and color depth of the framebuffer, the DAC, the
610
 * pseudo_palette, and the logo data will be adjusted accordingly.
611
 *
612
 * Case 1 - linux_logo_clut224:
613
 * Color exceeds the number of console colors (16), thus we set the hardware DAC
614
 * using fb_set_cmap() appropriately.  The "needs_cmapreset"  flag will be set.
615
 *
616
 * For visuals that require color info from the pseudo_palette, we also construct
617
 * one for temporary use. The "needs_directpalette" or "needs_truepalette" flags
618
 * will be set.
619
 *
620
 * Case 2 - linux_logo_vga16:
621
 * The number of colors just matches the console colors, thus there is no need
622
 * to set the DAC or the pseudo_palette.  However, the bitmap is packed, ie,
623
 * each byte contains color information for two pixels (upper and lower nibble).
624
 * To be consistent with fb_imageblit() usage, we therefore separate the two
625
 * nibbles into separate bytes. The "depth" flag will be set to 4.
626
 *
627
 * Case 3 - linux_logo_mono:
628
 * This is similar with Case 2.  Each byte contains information for 8 pixels.
629
 * We isolate each bit and expand each into a byte. The "depth" flag will
630
 * be set to 1.
631
 */
632
static struct logo_data {
633
	int depth;
634
	int needs_directpalette;
635
	int needs_truepalette;
636
	int needs_cmapreset;
637
	const struct linux_logo *logo;
638
} fb_logo;
639
 
640
int fb_prepare_logo(struct fb_info *info)
641
{
642
	memset(&fb_logo, 0, sizeof(struct logo_data));
643
 
644
	switch (info->fix.visual) {
645
	case FB_VISUAL_TRUECOLOR:
646
		if (info->var.bits_per_pixel >= 8)
647
			fb_logo.needs_truepalette = 1;
648
		break;
649
	case FB_VISUAL_DIRECTCOLOR:
650
		if (info->var.bits_per_pixel >= 24) {
651
			fb_logo.needs_directpalette = 1;
652
			fb_logo.needs_cmapreset = 1;
653
		}
654
		break;
655
	case FB_VISUAL_PSEUDOCOLOR:
656
		fb_logo.needs_cmapreset = 1;
657
		break;
658
	}
659
 
660
	/* Return if no suitable logo was found */
661
	fb_logo.logo = fb_find_logo(info->var.bits_per_pixel);
662
 
663
	if (!fb_logo.logo || fb_logo.logo->height > info->var.yres) {
664
		fb_logo.logo = NULL;
665
		return 0;
666
	}
667
	/* What depth we asked for might be different from what we get */
668
	if (fb_logo.logo->type == LINUX_LOGO_CLUT224)
669
		fb_logo.depth = 8;
670
	else if (fb_logo.logo->type == LINUX_LOGO_VGA16)
671
		fb_logo.depth = 4;
672
	else
673
		fb_logo.depth = 1;
674
	return fb_logo.logo->height;
675
}
676
 
677
int fb_show_logo(struct fb_info *info)
678
{
679
	u32 *palette = NULL, *saved_pseudo_palette = NULL;
680
	unsigned char *logo_new = NULL;
681
	struct fb_image image;
682
	int x;
683
 
684
	/* Return if the frame buffer is not mapped */
685
	if (fb_logo.logo == NULL)
686
		return 0;
687
 
688
	image.depth = fb_logo.depth;
689
	image.data = fb_logo.logo->data;
690
 
691
	if (fb_logo.needs_cmapreset)
692
		fb_set_logocmap(info, fb_logo.logo);
693
 
694
	if (fb_logo.needs_truepalette ||
695
	    fb_logo.needs_directpalette) {
696
		palette = kmalloc(256 * 4, GFP_KERNEL);
697
		if (palette == NULL)
698
			return 0;
699
 
700
		if (fb_logo.needs_truepalette)
701
			fb_set_logo_truepalette(info, fb_logo.logo, palette);
702
		else
703
			fb_set_logo_directpalette(info, fb_logo.logo, palette);
704
 
705
		saved_pseudo_palette = info->pseudo_palette;
706
		info->pseudo_palette = palette;
707
	}
708
 
709
	if (fb_logo.depth == 4) {
710
		logo_new = kmalloc(fb_logo.logo->width * fb_logo.logo->height,
711
				   GFP_KERNEL);
712
		if (logo_new == NULL) {
713
			if (palette)
714
				kfree(palette);
715
			if (saved_pseudo_palette)
716
				info->pseudo_palette = saved_pseudo_palette;
717
			return 0;
718
		}
719
		image.data = logo_new;
720
		fb_set_logo(info, fb_logo.logo, logo_new, fb_logo.depth);
721
	}
722
 
723
	image.width = fb_logo.logo->width;
724
	image.height = fb_logo.logo->height;
725
	image.dy = 0;
726
 
727
	for (x = 0; x < num_online_cpus() * (fb_logo.logo->width + 8) &&
728
	     x <= info->var.xres-fb_logo.logo->width; x += (fb_logo.logo->width + 8)) {
729
		image.dx = x;
730
		info->fbops->fb_imageblit(info, &image);
731
		//atomic_dec(&info->pixmap.count);
732
		//smp_mb__after_atomic_dec();
733
	}
734
 
735
	if (palette != NULL)
736
		kfree(palette);
737
	if (saved_pseudo_palette != NULL)
738
		info->pseudo_palette = saved_pseudo_palette;
739
	if (logo_new != NULL)
740
		kfree(logo_new);
741
	return fb_logo.logo->height;
742
}
743
#else
744
int fb_prepare_logo(struct fb_info *info) { return 0; }
745
int fb_show_logo(struct fb_info *info) { return 0; }
746
#endif /* CONFIG_LOGO */
747
 
748
static int fbmem_read_proc(char *buf, char **start, off_t offset,
749
			   int len, int *eof, void *private)
750
{
751
	struct fb_info **fi;
752
	int clen;
753
 
754
	clen = 0;
755
	for (fi = registered_fb; fi < &registered_fb[FB_MAX] && len < 4000; fi++)
756
		if (*fi)
757
			clen += sprintf26(buf + clen, "%d %s\n",
758
				        (*fi)->node,
759
				        (*fi)->fix.id);
760
	*start = buf + offset;
761
	if (clen > offset)
762
		clen -= offset;
763
	else
764
		clen = 0;
765
	return clen < len ? clen : len;
766
}
767
 
768
static ssize_t
769
fb_read(struct file *file, char *buf, size_t count, loff_t *ppos)
770
{
771
	unsigned long p = *ppos;
772
	struct inode *inode = file->f_dentry->d_inode;
773
	int fbidx = iminor(inode);
774
	struct fb_info *info = registered_fb[fbidx];
775
 
776
	if (!info || ! info->screen_base)
777
		return -ENODEV;
778
 
779
	if (info->fbops->fb_read)
780
		return info->fbops->fb_read(file, buf, count, ppos);
781
 
782
	if (p >= info->fix.smem_len)
783
	    return 0;
784
	if (count >= info->fix.smem_len)
785
	    count = info->fix.smem_len;
786
	if (count + p > info->fix.smem_len)
787
		count = info->fix.smem_len - p;
788
	if (info->fbops->fb_sync)
789
		info->fbops->fb_sync(info);
790
	if (count) {
791
	    char *base_addr;
792
 
793
	    base_addr = info->screen_base;
794
	    count -= copy_to_user(buf, base_addr+p, count);
795
	    if (!count)
796
		return -EFAULT;
797
	    *ppos += count;
798
	}
799
	return count;
800
}
801
 
802
static ssize_t
803
fb_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
804
{
805
	unsigned long p = *ppos;
806
	struct inode *inode = file->f_dentry->d_inode;
807
	int fbidx = iminor(inode);
808
	struct fb_info *info = registered_fb[fbidx];
809
	int err;
810
 
811
	if (!info || !info->screen_base)
812
		return -ENODEV;
813
 
814
	if (info->fbops->fb_write)
815
		return info->fbops->fb_write(file, buf, count, ppos);
816
 
817
	if (p > info->fix.smem_len)
818
	    return -ENOSPC;
819
	if (count >= info->fix.smem_len)
820
	    count = info->fix.smem_len;
821
	err = 0;
822
	if (count + p > info->fix.smem_len) {
823
	    count = info->fix.smem_len - p;
824
	    err = -ENOSPC;
825
	}
826
	if (info->fbops->fb_sync)
827
		info->fbops->fb_sync(info);
828
	if (count) {
829
	    char *base_addr;
830
 
831
	    base_addr = info->screen_base;
832
	    count -= copy_from_user(base_addr+p, buf, count);
833
	    *ppos += count;
834
	    err = -EFAULT;
835
	}
836
	if (count)
837
		return count;
838
	return err;
839
}
840
 
841
#ifdef CONFIG_KMOD
842
static void try_to_load(int fb)
843
{
844
	request_module("fb%d", fb);
845
}
846
#endif /* CONFIG_KMOD */
847
 
848
int
849
fb_cursor(struct fb_info *info, struct fb_cursor *sprite)
850
{
851
	struct fb_cursor cursor;
852
	int err;
853
 
854
	if (copy_from_user(&cursor, sprite, sizeof(struct fb_cursor)))
855
		return -EFAULT;
856
 
857
	if (cursor.set & FB_CUR_SETCUR)
858
		info->cursor.enable = 1;
859
 
860
	if (cursor.set & FB_CUR_SETCMAP) {
861
		err = fb_copy_cmap(&cursor.image.cmap, &sprite->image.cmap, 1);
862
		if (err)
863
			return err;
864
	}
865
 
866
	if (cursor.set & FB_CUR_SETSHAPE) {
867
		int size = ((cursor.image.width + 7) >> 3) * cursor.image.height;
868
		if ((cursor.image.height != info->cursor.image.height) ||
869
		    (cursor.image.width != info->cursor.image.width))
870
			cursor.set |= FB_CUR_SETSIZE;
871
 
872
		cursor.image.data = kmalloc(size, GFP_KERNEL);
873
		if (!cursor.image.data)
874
			return -ENOMEM;
875
 
876
		cursor.mask = kmalloc(size, GFP_KERNEL);
877
		if (!cursor.mask) {
878
			kfree(cursor.image.data);
879
			return -ENOMEM;
880
		}
881
 
882
		if (copy_from_user(&cursor.image.data, sprite->image.data, size) ||
883
		    copy_from_user(cursor.mask, sprite->mask, size)) {
884
			kfree(cursor.image.data);
885
			kfree(cursor.mask);
886
			return -EFAULT;
887
		}
888
	}
889
	info->cursor.set = cursor.set;
890
	info->cursor.rop = cursor.rop;
891
	err = info->fbops->fb_cursor(info, &cursor);
892
	return err;
893
}
894
 
895
int
896
fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var)
897
{
898
        int xoffset = var->xoffset;
899
        int yoffset = var->yoffset;
900
        int err;
901
 
902
        if (xoffset < 0 || yoffset < 0 || !info->fbops->fb_pan_display ||
903
            xoffset + info->var.xres > info->var.xres_virtual ||
904
            yoffset + info->var.yres > info->var.yres_virtual)
905
                return -EINVAL;
906
	if ((err = info->fbops->fb_pan_display(var, info)))
907
		return err;
908
        info->var.xoffset = var->xoffset;
909
        info->var.yoffset = var->yoffset;
910
        if (var->vmode & FB_VMODE_YWRAP)
911
                info->var.vmode |= FB_VMODE_YWRAP;
912
        else
913
                info->var.vmode &= ~FB_VMODE_YWRAP;
914
        return 0;
915
}
916
 
917
int
918
fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
919
{
920
	int err;
921
 
922
	if (memcmp(&info->var, var, sizeof(struct fb_var_screeninfo))) {
923
		if (!info->fbops->fb_check_var) {
924
			*var = info->var;
925
			return 0;
926
		}
927
 
928
		if ((err = info->fbops->fb_check_var(var, info)))
929
			return err;
930
 
931
		if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
932
			info->var = *var;
933
 
934
			if (info->fbops->fb_set_par)
935
				info->fbops->fb_set_par(info);
936
 
937
			fb_pan_display(info, &info->var);
938
 
939
			fb_set_cmap(&info->cmap, 1, info);
940
		}
941
	}
942
	return 0;
943
}
944
 
945
int
946
fb_blank(struct fb_info *info, int blank)
947
{
948
	/* ??? Variable sized stack allocation.  */
949
	u16 black[info->cmap.len];
950
	struct fb_cmap cmap;
951
 
952
	if (info->fbops->fb_blank && !info->fbops->fb_blank(blank, info))
953
		return 0;
954
	if (blank) {
955
		memset(black, 0, info->cmap.len * sizeof(u16));
956
		cmap.red = cmap.green = cmap.blue = black;
957
		cmap.transp = info->cmap.transp ? black : NULL;
958
		cmap.start = info->cmap.start;
959
		cmap.len = info->cmap.len;
960
	} else
961
		cmap = info->cmap;
962
	return fb_set_cmap(&cmap, 1, info);
963
}
964
 
484 giacomo 965
int debx,deby,debb;
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:
483 giacomo 1046
		return fb_blank(info, arg);
466 giacomo 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;
477 giacomo 1158
	struct fb_fillrect rect;
476 giacomo 1159
	int res = 0;
466 giacomo 1160
 
1161
	if (fbidx >= FB_MAX)
1162
		return -ENODEV;
1163
#ifdef CONFIG_KMOD
1164
	if (!(info = registered_fb[fbidx]))
1165
		try_to_load(fbidx);
1166
#endif /* CONFIG_KMOD */
1167
	if (!(info = registered_fb[fbidx]))
1168
		return -ENODEV;
1169
	if (!try_module_get(info->fbops->owner))
1170
		return -ENODEV;
1171
	if (info->fbops->fb_open) {
1172
		res = info->fbops->fb_open(info,1);
1173
		if (res)
1174
			module_put(info->fbops->owner);
1175
	}
475 giacomo 1176
 
484 giacomo 1177
	if (info->fbops->fb_set_par)
1178
          info->fbops->fb_set_par(info);
476 giacomo 1179
	fb_pan_display(info, &info->var);
1180
 
477 giacomo 1181
	rect.dx = 0;
1182
	rect.dy = 0;
1183
	rect.width = info->var.xres;
1184
	rect.height = info->var.yres;
1185
	rect.color = 0;
1186
	rect.rop = ROP_COPY;
1187
 
1188
	cfb_fillrect(info,&rect);
1189
 
476 giacomo 1190
	if (info->var.bits_per_pixel >= 8) {
1191
 
1192
	  fb_prepare_logo(info);
1193
	  fb_show_logo(info);
1194
 
1195
	}
475 giacomo 1196
 
466 giacomo 1197
	return res;
1198
}
1199
 
470 giacomo 1200
static int
466 giacomo 1201
fb_release(struct inode *inode, struct file *file)
1202
{
1203
	int fbidx = iminor(inode);
1204
	struct fb_info *info;
1205
 
1206
	lock_kernel();
1207
	info = registered_fb[fbidx];
1208
	if (info->fbops->fb_release)
1209
		info->fbops->fb_release(info,1);
1210
	module_put(info->fbops->owner);
1211
	unlock_kernel();
475 giacomo 1212
 
466 giacomo 1213
	return 0;
1214
}
1215
 
1216
static struct file_operations fb_fops = {
1217
	.owner =	THIS_MODULE,
1218
	.read =		fb_read,
1219
	.write =	fb_write,
1220
	.ioctl =	fb_ioctl,
1221
	.mmap =		fb_mmap,
1222
	.open =		fb_open,
1223
	.release =	fb_release,
1224
#ifdef HAVE_ARCH_FB_UNMAPPED_AREA
1225
	.get_unmapped_area = get_fb_unmapped_area,
1226
#endif
1227
};
1228
 
1229
/**
1230
 *	register_framebuffer - registers a frame buffer device
1231
 *	@fb_info: frame buffer info structure
1232
 *
1233
 *	Registers a frame buffer device @fb_info.
1234
 *
1235
 *	Returns negative errno on error, or zero for success.
1236
 *
1237
 */
1238
 
1239
int
1240
register_framebuffer(struct fb_info *fb_info)
1241
{
1242
	int i;
1243
 
1244
	if (num_registered_fb == FB_MAX)
1245
		return -ENXIO;
1246
	num_registered_fb++;
1247
	for (i = 0 ; i < FB_MAX; i++)
1248
		if (!registered_fb[i])
1249
			break;
1250
	fb_info->node = i;
1251
 
1252
	if (fb_info->pixmap.addr == NULL) {
1253
		fb_info->pixmap.addr = kmalloc(FBPIXMAPSIZE, GFP_KERNEL);
1254
		if (fb_info->pixmap.addr) {
1255
			fb_info->pixmap.size = FBPIXMAPSIZE;
1256
			fb_info->pixmap.buf_align = 1;
1257
			fb_info->pixmap.scan_align = 1;
1258
			fb_info->pixmap.flags = FB_PIXMAP_DEFAULT;
1259
		}
1260
	}
1261
	fb_info->pixmap.offset = 0;
1262
	if (fb_info->pixmap.outbuf == NULL)
1263
		fb_info->pixmap.outbuf = sys_outbuf;
1264
	if (fb_info->pixmap.inbuf == NULL)
1265
		fb_info->pixmap.inbuf = sys_inbuf;
1266
	spin_lock_init(&fb_info->pixmap.lock);
1267
 
1268
	registered_fb[i] = fb_info;
1269
 
1270
	devfs_mk_cdev(MKDEV(FB_MAJOR, i),
1271
			S_IFCHR | S_IRUGO | S_IWUGO, "fb/%d", i);
1272
	return 0;
1273
}
1274
 
1275
 
1276
/**
1277
 *	unregister_framebuffer - releases a frame buffer device
1278
 *	@fb_info: frame buffer info structure
1279
 *
1280
 *	Unregisters a frame buffer device @fb_info.
1281
 *
1282
 *	Returns negative errno on error, or zero for success.
1283
 *
1284
 */
1285
 
1286
int
1287
unregister_framebuffer(struct fb_info *fb_info)
1288
{
1289
	int i;
1290
 
1291
	i = fb_info->node;
1292
	if (!registered_fb[i])
1293
		return -EINVAL;
1294
	devfs_remove("fb/%d", i);
1295
 
1296
	if (fb_info->pixmap.addr)
1297
		kfree(fb_info->pixmap.addr);
1298
	registered_fb[i]=NULL;
1299
	num_registered_fb--;
1300
	return 0;
1301
}
1302
 
1303
 
1304
/**
1305
 *	fbmem_init - init frame buffer subsystem
1306
 *
1307
 *	Initialize the frame buffer subsystem.
1308
 *
1309
 *	NOTE: This function is _only_ to be called by drivers/char/mem.c.
1310
 *
1311
 */
1312
 
1313
void __init
1314
fbmem_init(void)
1315
{
1316
	int i;
1317
 
1318
	create_proc_read_entry("fb", 0, 0, fbmem_read_proc, NULL);
1319
 
1320
	devfs_mk_dir("fb");
1321
	if (register_chrdev(FB_MAJOR,"fb",&fb_fops))
1322
		printk("unable to get major %d for fb devs\n", FB_MAJOR);
1323
 
1324
#ifdef CONFIG_FB_OF
1325
	if (ofonly) {
1326
		offb_init();
1327
		return;
1328
	}
1329
#endif
1330
 
1331
	/*
1332
	 *  Probe for all builtin frame buffer devices
1333
	 */
1334
	for (i = 0; i < num_pref_init_funcs; i++)
1335
		pref_init_funcs[i]();
1336
 
1337
	for (i = 0; i < NUM_FB_DRIVERS; i++)
1338
		if (fb_drivers[i].init)
1339
			fb_drivers[i].init();
1340
}
1341
 
469 giacomo 1342
extern int linuxcomp_setfd(struct inode *i, int i_rdev);
466 giacomo 1343
 
469 giacomo 1344
/* Shark Inode emulation */
1022 mauro 1345
int fb_open_inode(int num)
1346
{
1347
	struct inode *i;
469 giacomo 1348
 
1022 mauro 1349
	i = (struct inode *)kmalloc(sizeof(struct inode),GFP_KERNEL);
1350
 
1351
	linuxcomp_setfd(i,num);
1352
 
1353
	if (fb_open(i,NULL)) {
1354
		kfree(i);
1355
		return -1;
1356
	}
1357
 
1358
	kfree(i);
1359
	return 0;
470 giacomo 1360
}
1361
 
1362
/* Shark Inode emulation */
1022 mauro 1363
int fb_close_inode(int num)
1364
{
1365
	struct inode *i;
470 giacomo 1366
 
1022 mauro 1367
	i = (struct inode *)kmalloc(sizeof(struct inode),GFP_KERNEL);
469 giacomo 1368
 
1022 mauro 1369
	linuxcomp_setfd(i,num);
469 giacomo 1370
 
1022 mauro 1371
	if(fb_release(i,NULL)) {
1372
		kfree(i);
1373
		return -1;
1374
	}
469 giacomo 1375
 
1022 mauro 1376
	kfree(i);
469 giacomo 1377
 
1022 mauro 1378
	return 0;
1379
}
470 giacomo 1380
 
1022 mauro 1381
int fb_set_mode_inode(int num, unsigned char *modeopt)
1382
{
1383
	struct fb_var_screeninfo var;
1384
	struct fb_info *info = registered_fb[num];
1385
	struct fb_fillrect rect;
469 giacomo 1386
 
1022 mauro 1387
	fb_find_mode(&var,info,modeopt,NULL,0,NULL,0);
469 giacomo 1388
 
1022 mauro 1389
	var.xoffset = 0;
1390
	var.yoffset = 0;
1391
	var.xres_virtual = var.xres;
1392
	var.yres_virtual = var.yres;
472 giacomo 1393
 
1022 mauro 1394
	if (info->fbops->fb_check_var)
1395
		info->fbops->fb_check_var(&var, info);
472 giacomo 1396
 
1022 mauro 1397
	memcpy(&(info->var),&var,sizeof(struct fb_var_screeninfo));
483 giacomo 1398
 
1022 mauro 1399
	if (info->fbops->fb_set_par)
1400
	info->fbops->fb_set_par(info);
1401
	fb_pan_display(info, &info->var);
472 giacomo 1402
 
1022 mauro 1403
	if (info->var.bits_per_pixel > 8)
1404
		info->fix.visual = FB_VISUAL_TRUECOLOR;
484 giacomo 1405
 
1022 mauro 1406
	rect.dx = 0;
1407
	rect.dy = 0;
1408
	rect.width = info->var.xres;
1409
	rect.height = info->var.yres;
1410
	rect.color = 0;
1411
	rect.rop = ROP_COPY;
484 giacomo 1412
 
1022 mauro 1413
	cfb_fillrect(info,&rect);
484 giacomo 1414
 
1022 mauro 1415
	return 0;
472 giacomo 1416
}
1417
 
466 giacomo 1418
/**
1419
 *	video_setup - process command line options
1420
 *	@options: string of options
1421
 *
1422
 *	Process command line options for frame buffer subsystem.
1423
 *
1424
 *	NOTE: This function is a __setup and __init function.
1425
 *
1426
 *	Returns zero.
1427
 *
1428
 */
1429
 
1430
int __init video_setup(char *options)
1431
{
1432
	int i, j;
1433
 
1434
	if (!options || !*options)
1435
		return 0;
1436
 
1437
#ifdef CONFIG_FB_OF
1438
	if (!strcmp(options, "ofonly")) {
1439
		ofonly = 1;
1440
		return 0;
1441
	}
1442
#endif
1443
 
1444
	if (num_pref_init_funcs == FB_MAX)
1445
		return 0;
1446
 
1447
	for (i = 0; i < NUM_FB_DRIVERS; i++) {
1448
		j = strlen(fb_drivers[i].name);
1449
		if (!strncmp(options, fb_drivers[i].name, j) &&
1450
			options[j] == ':') {
1451
			if (!strcmp(options+j+1, "off"))
1452
				fb_drivers[i].init = NULL;
1453
			else {
1454
				if (fb_drivers[i].init) {
1455
					pref_init_funcs[num_pref_init_funcs++] =
1456
						fb_drivers[i].init;
1457
					fb_drivers[i].init = NULL;
1458
				}
1459
				if (fb_drivers[i].setup)
1460
					fb_drivers[i].setup(options+j+1);
1461
			}
1462
			return 0;
1463
		}
1464
	}
1465
 
1466
	/*
1467
	 * If we get here no fb was specified.
1468
	 * We consider the argument to be a global video mode option.
1469
	 */
468 giacomo 1470
	//global_mode_option = options;
466 giacomo 1471
	return 0;
1472
}
1473
 
1474
__setup("video=", video_setup);
1475
 
1476
    /*
1477
     *  Visible symbols for modules
1478
     */
1479
 
1480
EXPORT_SYMBOL(register_framebuffer);
1481
EXPORT_SYMBOL(unregister_framebuffer);
1482
EXPORT_SYMBOL(num_registered_fb);
1483
EXPORT_SYMBOL(registered_fb);
1484
EXPORT_SYMBOL(fb_prepare_logo);
1485
EXPORT_SYMBOL(fb_show_logo);
1486
EXPORT_SYMBOL(fb_set_var);
1487
EXPORT_SYMBOL(fb_blank);
1488
EXPORT_SYMBOL(fb_pan_display);
1489
EXPORT_SYMBOL(fb_get_buffer_offset);
1490
EXPORT_SYMBOL(move_buf_unaligned);
1491
EXPORT_SYMBOL(move_buf_aligned);
1492
 
1493
MODULE_LICENSE("GPL");