/[linux-patches]/genpatches-2.6/trunk/2.6.13-pre/4505_vesafb-tng-0.9-rc7-r1.patch
Gentoo

Contents of /genpatches-2.6/trunk/2.6.13-pre/4505_vesafb-tng-0.9-rc7-r1.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 96 - (show annotations) (download) (as text)
Wed Jul 13 13:19:49 2005 UTC (13 years, 10 months ago) by dsd
File MIME type: text/x-diff
File size: 74872 byte(s)
New fbsplash and vesafb-tng
1 diff --git a/Documentation/fb/vesafb.txt b/Documentation/fb/vesafb.txt
2 --- a/Documentation/fb/vesafb.txt
3 +++ b/Documentation/fb/vesafb.txt
4 @@ -2,16 +2,18 @@
5 What is vesafb?
6 ===============
7
8 -This is a generic driver for a graphic framebuffer on intel boxes.
9 +Vesafb is a generic framebuffer driver for x86 and x86_64 boxes.
10
11 -The idea is simple: Turn on graphics mode at boot time with the help
12 -of the BIOS, and use this as framebuffer device /dev/fb0, like the m68k
13 -(and other) ports do.
14 -
15 -This means we decide at boot time whenever we want to run in text or
16 -graphics mode. Switching mode later on (in protected mode) is
17 -impossible; BIOS calls work in real mode only. VESA BIOS Extensions
18 -Version 2.0 are required, because we need a linear frame buffer.
19 +VESA BIOS Extensions Version 2.0 are required, because we need a linear
20 +frame buffer. VBE 3.0 is required if you want to use modes with a higher
21 +(than the standard 60Hz) refresh rate.
22 +
23 +The VESA framebuffer driver comes in two flavors - the standard vesafb
24 +and vesafb-tng. Vesafb-tng is available only on 32-bit x86 due to the
25 +technology it uses (vm86). Vesafb-tng has more features than vesafb
26 +(adjusting the refresh rate on VBE3.0-compliant boards, switching the
27 +video mode without rebooting, selecting a mode by providing its
28 +modedb name, and more) but might be unstable on some systems.
29
30 Advantages:
31
32 @@ -29,16 +31,27 @@ Disadvantages:
33 How to use it?
34 ==============
35
36 -Switching modes is done using the vga=... boot parameter. Read
37 -Documentation/svga.txt for details.
38 -
39 -You should compile in both vgacon (for text mode) and vesafb (for
40 -graphics mode). Which of them takes over the console depends on
41 -whenever the specified mode is text or graphics.
42 -
43 -The graphic modes are NOT in the list which you get if you boot with
44 -vga=ask and hit return. The mode you wish to use is derived from the
45 -VESA mode number. Here are those VESA mode numbers:
46 +If you are running your system on hardware platform where vm86 is supported
47 +(this is 32-bit x86 only as of the time of writing this document) and you
48 +decide to use vesafb-tng, you can either the driver into the kernel or use it
49 +as a module. The graphic mode you want to use is in both cases specified using
50 +the standard modedb format.
51 +
52 +If your system doesn't support vm86 calls yet (all 64-bit platforms), things
53 +get a little more tricky. Since on such systems you can't do BIOS calls from
54 +protected mode in which kernel runs, you have to decide at boot time whenever
55 +you want to run in text or in graphics mode. Switching mode later on is
56 +impossible. Switching modes is done using the vga=... boot parameter. Read
57 +Documentation/svga.txt for details. Below is a more detailed description of
58 +what to do on systems using the standard vesafb driver.
59 +
60 +You should compile in both vgacon (for text mode) and vesafb (for graphics mode).
61 +Which of them takes over the console depends on whenever the specified mode is
62 +text or graphics.
63 +
64 +The graphic modes are NOT in the list which you get if you boot with vga=ask
65 +and hit return. The mode you wish to use is derived from the VESA mode number.
66 +Here are those VESA mode numbers:
67
68 | 640x480 800x600 1024x768 1280x1024
69 ----+-------------------------------------
70 @@ -47,8 +60,7 @@ VESA mode number. Here are those VESA mo
71 64k | 0x111 0x114 0x117 0x11A
72 16M | 0x112 0x115 0x118 0x11B
73
74 -The video mode number of the Linux kernel is the VESA mode number plus
75 -0x200.
76 +The video mode number of the Linux kernel is the VESA mode number plus 0x200.
77
78 Linux_kernel_mode_number = VESA_mode_number + 0x200
79
80 @@ -61,10 +73,10 @@ So the table for the Kernel mode numbers
81 64k | 0x311 0x314 0x317 0x31A
82 16M | 0x312 0x315 0x318 0x31B
83
84 -To enable one of those modes you have to specify "vga=ask" in the
85 -lilo.conf file and rerun LILO. Then you can type in the desired
86 -mode at the "vga=ask" prompt. For example if you like to use
87 -1024x768x256 colors you have to say "305" at this prompt.
88 +To enable one of those modes you have to specify "vga=ask" in the lilo.conf
89 +file and rerun LILO. Then you can type in the desired mode at the "vga=ask"
90 +prompt. For example if you like to use 1024x768x256 colors you have to say
91 +"305" at this prompt.
92
93 If this does not work, this might be because your BIOS does not support
94 linear framebuffers or because it does not support this mode at all.
95 @@ -77,6 +89,7 @@ Extensions v2.0 are required, 1.2 is NOT
96 2. Note: Some newer versions of LILO appear to work with those hex values,
97 if you set the 0x in front of the numbers.
98
99 +
100 X11
101 ===
102
103 @@ -86,65 +99,73 @@ It depends on X-Server and graphics boar
104
105 The X-Server must restore the video mode correctly, else you end up
106 with a broken console (and vesafb cannot do anything about this).
107 +With vesafb-tng chances are that the console will be restored properly
108 +even if the X server messed up the video mode.
109
110
111 Refresh rates
112 =============
113
114 -There is no way to change the vesafb video mode and/or timings after
115 -booting linux. If you are not happy with the 60 Hz refresh rate, you
116 -have these options:
117 +With VBE3.0 compatible BIOSes and vesafb-tng it is possible to change
118 +the refresh rate either at boot time (by specifying the @<rr> part of
119 +the mode name) or later, using the fbset utility.
120 +
121 +With VBE2.0 there is no way to change the mode timings after booting
122 +Linux. If you are not happy with the 60 Hz refresh rate, you have
123 +these options:
124
125 - * configure and load the DOS-Tools for your the graphics board (if
126 - available) and boot linux with loadlin.
127 + * configure and load the DOS tools for your the graphics board (if
128 + available) and boot Linux with loadlin.
129 * use a native driver (matroxfb/atyfb) instead if vesafb. If none
130 is available, write a new one!
131 - * VBE 3.0 might work too. I have neither a gfx board with VBE 3.0
132 - support nor the specs, so I have not checked this yet.
133 + * use a BIOS editor to change the default refresh rate (such an
134 + editor does exist at least for ATI Radeon BIOSes).
135 + * if you're running a non-vm86 and VBE3.0-compatible system, you can
136 + use a kernel patch to hard-code some mode timings in the kernel and
137 + use these while setting the graphic mode at boot time.
138
139
140 Configuration
141 =============
142
143 -The VESA BIOS provides protected mode interface for changing
144 -some parameters. vesafb can use it for palette changes and
145 -to pan the display. It is turned off by default because it
146 -seems not to work with some BIOS versions, but there are options
147 -to turn it on.
148 -
149 -You can pass options to vesafb using "video=vesafb:option" on
150 -the kernel command line. Multiple options should be separated
151 -by comma, like this: "video=vesafb:ypan,invers"
152 -
153 -Accepted options:
154 -
155 -invers no comment...
156 -
157 -ypan enable display panning using the VESA protected mode
158 - interface. The visible screen is just a window of the
159 +The VESA BIOS provides protected mode interface for changing some parameters.
160 +vesafb can use it for palette changes and to pan the display. It is turned
161 +off by default because it seems not to work with some BIOS versions, but there
162 +are options to turn it on.
163 +
164 +You can pass options to vesafb using "video=vesafb:option" on the kernel
165 +command line. Multiple options should be separated by comma, like this:
166 +"video=vesafb:ypan,1024x768-32@85"
167 +
168 +Accepted options (both vesafb and vesafb-tng):
169 +
170 +ypan Enable display panning using the VESA protected mode
171 + interface or vm86 calls. The visible screen is just a window of the
172 video memory, console scrolling is done by changing the
173 start of the window.
174 pro: * scrolling (fullscreen) is fast, because there is
175 no need to copy around data.
176 - * You'll get scrollback (the Shift-PgUp thing),
177 + * you'll get scrollback (the Shift-PgUp thing),
178 the video memory can be used as scrollback buffer
179 - kontra: * scrolling only parts of the screen causes some
180 + con: * scrolling only parts of the screen causes some
181 ugly flicker effects (boot logo flickers for
182 example).
183
184 -ywrap Same as ypan, but assumes your gfx board can wrap-around
185 - the video memory (i.e. starts reading from top if it
186 - reaches the end of video memory). Faster than ypan.
187 -
188 -redraw scroll by redrawing the affected part of the screen, this
189 - is the safe (and slow) default.
190 +ywrap Same as ypan, but assumes your gfx board can wrap-around the video
191 + memory (i.e. starts reading from top if it reaches the end of video
192 + memory). Faster than ypan.
193
194 +redraw Scroll by redrawing the affected part of the screen, this is the
195 + safe (and slow) default.
196
197 -vgapal Use the standard vga registers for palette changes.
198 +vgapal Use the standard VGA registers for palette changes.
199 This is the default.
200 +
201 pmipal Use the protected mode interface for palette changes.
202
203 -mtrr setup memory type range registers for the vesafb framebuffer.
204 +mtrr Setup memory type range registers for the vesafb framebuffer.
205 +
206 +nomtrr Do not use memory type range registers for vesafb.
207
208 vremap:n
209 remap 'n' MiB of video RAM. If 0 or not specified, remap memory
210 @@ -156,12 +177,96 @@ vtotal:n
211 if the video BIOS of your card incorrectly determines the total
212 amount of video RAM, use this option to override the BIOS (in MiB).
213
214 -Have fun!
215 +Options accepted only by vesafb-tng:
216 +
217 +<mode> The mode you want to set, in the standard modedb format. Refer to
218 + modedb.txt for detailed description. If you specify a mode that is
219 + not supported by your board's BIOS, vesafb will attempt to set a
220 + similar mode. The list of supported modes can be found in
221 + /proc/fbx/modes, where x is the framebuffer number (usually 0).
222 + When vesafb is compiled as a module, the mode string should be
223 + provided as a value of the parameter 'mode'.
224 +
225 +vbemode:x
226 + Force the use of VBE mode x. The mode will only be set if it's
227 + found in VBE-provided list of supported modes.
228 + NOTE: The mode number 'x' should be specified in VESA mode number
229 + notation, not the Linux kernel one (ie. 257 instead of 769).
230 + HINT: If you use this option because normal <mode> parameter does
231 + not work for you and you use a X server, you'll probably want to
232 + set the 'nocrtc' option to ensure that the video mode is properly
233 + restored after console <-> X switches.
234 +
235 +nocrtc Do not use CRTC timings while setting the graphic mode. This option
236 + makes sence only with VBE3.0 compliant systems. Use it if you have
237 + problems with the modes set in the standard way. Note that specifying
238 + this option means the refresh rate will be ignored and will stay at
239 + your BIOS' default (60 Hz).
240 +
241 +noedid Do not try to fetch and use EDID-provided modes.
242 +
243 +gtf Force the use of VESA's GTF (Generalized Timing Formula). Specifying
244 + this will cause vesafb to skip it's internal modedb and EDID-modedb
245 + and jump straight to the GTF part of the code (normally used only is
246 + everything else failed). This can be useful if you want to get as much
247 + as possible from you graphics board but your BIOS doesn't support
248 + modes with refresh rates you require. Note that you may need to
249 + specify the maxhf, maxvf and maxclk parameters if they are not
250 + provided by EDID.
251 +
252 +Additionally, the following parameters may be provided. They all override the
253 +EDID-provided values and BIOS defaults. Refer to you monitor's specs to get
254 +the correct values for maxhf, maxvf and maxclk for your hardware.
255 +
256 +maxhf:n Maximum horizontal frequency (in kHz).
257 +maxvf:n Maximum vertical frequency (in Hz).
258 +maxclk:n Maximum pixel clock (in MHz).
259 +
260 +
261 +Vesafb-tng Technical details
262 +============================
263 +
264 +1. The driver architecture.
265 +
266 +The driver's code is stored in 3 files:
267 + /drivers/video/vesafb-tng.c
268 + /drivers/video/vesafb-thread.c
269 + /include/video/vesa.h
270 +
271 +vesafb-tng.c contains the main code. vesafb-thread.c contains code for the
272 +vesafb service thread. A separate thread is necessary because we need to remap
273 +memory in order to be able to use the vm86 calls. The service thread is started
274 +regardless of whether vesafb is compiled into the kernel or compiled as a
275 +module. This is necessary because of the active_mm stuff, better described in
276 +the header of vesafb-thread.c.
277 +
278 +2. The driver initialization
279 +
280 + o vesafb_vbe_init
281 + - get basic info about the graphics BIOS
282 + - fetch data about all modes supported by VBE
283 + - get info about the protected mode interface
284 + - get EDID data and attempt to create an EDID modedb
285 +
286 + o vesafb_probe
287 + - get service thread's PID (started earlier from fbmem.c)
288 + - call vesafb_vbe_init
289 + - find a matching VBE mode
290 + - try to find the specified mode in vesa_modes modedb
291 + - try to find the specified mode in the EDID modedb
292 + - try to calculate timings with the GTF
293 + - low level setup - request_mem_region, ioremap, etc.
294 + - setup /proc/fb<x>/modes and /proc/fb<x>/vbe_info
295
296 - Gerd
297 +Have fun!
298
299 --
300 +Original document for the vesafb driver by
301 Gerd Knorr <kraxel@goldbach.in-berlin.de>
302
303 -Minor (mostly typo) changes
304 -by Nico Schmoigl <schmoigl@rumms.uni-mannheim.de>
305 +Minor (mostly typo) changes by
306 +Nico Schmoigl <schmoigl@rumms.uni-mannheim.de>
307 +
308 +Extended documentation for vm86, VBE3.0 and vesafb-tng by
309 +Micha³ Januszewski <spock@gentoo.org>
310 +
311 diff --git a/arch/i386/boot/video.S b/arch/i386/boot/video.S
312 --- a/arch/i386/boot/video.S
313 +++ b/arch/i386/boot/video.S
314 @@ -164,10 +164,12 @@ basret: ret
315 # parameters in the default 80x25 mode -- these are set directly,
316 # because some very obscure BIOSes supply insane values.
317 mode_params:
318 +#ifdef CONFIG_FB_VESA_STD
319 #ifdef CONFIG_VIDEO_SELECT
320 cmpb $0, graphic_mode
321 jnz mopar_gr
322 #endif
323 +#endif
324 movb $0x03, %ah # Read cursor position
325 xorb %bh, %bh
326 int $0x10
327 @@ -200,6 +202,7 @@ mopar2: movb %al, %fs:(PARAM_VIDEO_LINES
328 ret
329
330 #ifdef CONFIG_VIDEO_SELECT
331 +#ifdef CONFIG_FB_VESA_STD
332 # Fetching of VESA frame buffer parameters
333 mopar_gr:
334 leaw modelist+1024, %di
335 @@ -278,6 +281,7 @@ dac_done:
336 movw %es, %fs:(PARAM_VESAPM_SEG)
337 movw %di, %fs:(PARAM_VESAPM_OFF)
338 no_pm: ret
339 +#endif
340
341 # The video mode menu
342 mode_menu:
343 @@ -492,10 +496,12 @@ mode_set:
344
345 cmpb $VIDEO_FIRST_V7>>8, %ah
346 jz setv7
347 -
348 +
349 +#ifdef CONFIG_FB_VESA_STD
350 cmpb $VIDEO_FIRST_VESA>>8, %ah
351 jnc check_vesa
352 -
353 +#endif
354 +
355 orb %ah, %ah
356 jz setmenu
357
358 @@ -567,6 +573,7 @@ setr1: lodsw
359 movw -4(%si), %ax # Fetch mode ID
360 jmp _m_s
361
362 +#ifdef CONFIG_FB_VESA_STD
363 check_vesa:
364 leaw modelist+1024, %di
365 subb $VIDEO_FIRST_VESA>>8, %bh
366 @@ -600,6 +607,7 @@ check_vesa:
367 ret
368
369 _setbad: jmp setbad # Ugly...
370 +#endif
371
372 # Recalculate vertical display end registers -- this fixes various
373 # inconsistencies of extended modes on many adapters. Called when
374 diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
375 --- a/drivers/video/Kconfig
376 +++ b/drivers/video/Kconfig
377 @@ -493,7 +493,7 @@ config FB_TGA
378 cards. Say Y if you have one of those.
379
380 config FB_VESA
381 - bool "VESA VGA graphics support"
382 + tristate "VESA VGA graphics support"
383 depends on (FB = y) && (X86 || X86_64)
384 select FB_CFB_FILLRECT
385 select FB_CFB_COPYAREA
386 @@ -505,6 +505,48 @@ config FB_VESA
387 You will get a boot time penguin logo at no additional cost. Please
388 read <file:Documentation/fb/vesafb.txt>. If unsure, say Y.
389
390 +choice
391 + prompt "VESA driver type"
392 + depends on FB_VESA
393 + default FB_VESA_STD if X86_64
394 + default FB_VESA_TNG if X86
395 +
396 +config FB_VESA_STD
397 + bool "vesafb"
398 + help
399 + This is the frame buffer device driver for generic VESA 2.0
400 + compliant graphic cards. The older VESA 1.2 cards are not supported.
401 + You will get a boot time penguin logo at no additional cost. Please
402 + read <file:Documentation/fb/vesafb.txt>. Choose this driver if you
403 + are experiencing problems with vesafb-tng or if you own a 64-bit system.
404 +
405 + Note that this driver cannot be compiled as a module.
406 +
407 +config FB_VESA_TNG
408 + bool "vesafb-tng"
409 + depends on !X86_64
410 + select FB_MODE_HELPERS
411 + help
412 + This is the frame buffer device driver for generic VESA 2.0
413 + compliant graphic cards. It is capable of taking advantage of
414 + VBE 3.0 features. With this driver you will be able to adjust
415 + the refresh rate (VBE 3.0 compliant boards only) and change
416 + the graphic mode on-the-fly.
417 +
418 + You will also get a boot time penguin logo at no additional cost. Please
419 + read <file:Documentation/fb/vesafb.txt>.
420 +
421 +endchoice
422 +
423 +config FB_VESA_DEFAULT_MODE
424 + string "VESA default mode"
425 + depends on FB_VESA_TNG
426 + default "640x480@60"
427 + help
428 + This option is used to determine the default mode vesafb is
429 + supposed to switch to in case no mode is provided as a kernel
430 + command line parameter.
431 +
432 config VIDEO_SELECT
433 bool
434 depends on FB_VESA
435 diff --git a/drivers/video/Makefile b/drivers/video/Makefile
436 --- a/drivers/video/Makefile
437 +++ b/drivers/video/Makefile
438 @@ -94,7 +94,22 @@ obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxf
439 obj-$(CONFIG_FB_IMX) += imxfb.o
440
441 # Platform or fallback drivers go here
442 -obj-$(CONFIG_FB_VESA) += vesafb.o
443 +ifeq ($(CONFIG_FB_VESA),m)
444 + ifeq ($(CONFIG_FB_VESA_STD),y)
445 + obj-y += vesafb.o
446 + else
447 + obj-m += vesafb-tng.o
448 + obj-y += vesafb-thread.o
449 + endif
450 +else
451 + ifeq ($(CONFIG_FB_VESA),y)
452 + ifeq ($(CONFIG_FB_VESA_STD),y)
453 + obj-y += vesafb.o
454 + else
455 + obj-y += vesafb-tng.o vesafb-thread.o
456 + endif
457 + endif
458 +endif
459 obj-$(CONFIG_FB_VGA16) += vga16fb.o vgastate.o
460 obj-$(CONFIG_FB_OF) += offb.o
461
462 diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
463 --- a/drivers/video/fbmem.c
464 +++ b/drivers/video/fbmem.c
465 @@ -52,6 +52,8 @@
466 * Frame buffer device initialization and setup routines
467 */
468
469 +extern int vesafb_init_thread(void);
470 +
471 #define FBPIXMAPSIZE (1024 * 8)
472
473 static struct notifier_block *fb_notifier_list;
474 @@ -1155,6 +1157,10 @@ fbmem_init(void)
475 printk(KERN_WARNING "Unable to create fb class; errno = %ld\n", PTR_ERR(fb_class));
476 fb_class = NULL;
477 }
478 +
479 +#if defined(CONFIG_FB_VESA_TNG) || defined(CONFIG_FB_VESA_TNG_MODULE)
480 + vesafb_init_thread();
481 +#endif
482 return 0;
483 }
484
485 diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
486 --- a/drivers/video/fbmon.c
487 +++ b/drivers/video/fbmon.c
488 @@ -516,7 +516,7 @@ static void get_detailed_timing(unsigned
489 * This function builds a mode database using the contents of the EDID
490 * data
491 */
492 -static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
493 +struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
494 {
495 struct fb_videomode *mode, *m;
496 unsigned char *block;
497 @@ -590,7 +590,7 @@ void fb_destroy_modedb(struct fb_videomo
498 kfree(modedb);
499 }
500
501 -static int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs)
502 +int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs)
503 {
504 int i, retval = 1;
505 unsigned char *block;
506 @@ -1178,9 +1178,17 @@ void fb_edid_to_monspecs(unsigned char *
507 {
508 specs = NULL;
509 }
510 +struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
511 +{
512 + return NULL;
513 +}
514 void fb_destroy_modedb(struct fb_videomode *modedb)
515 {
516 }
517 +int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs)
518 +{
519 + return 1;
520 +}
521 int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var,
522 struct fb_info *info)
523 {
524 @@ -1255,3 +1263,5 @@ EXPORT_SYMBOL(fb_edid_to_monspecs);
525 EXPORT_SYMBOL(fb_get_mode);
526 EXPORT_SYMBOL(fb_validate_mode);
527 EXPORT_SYMBOL(fb_destroy_modedb);
528 +EXPORT_SYMBOL(fb_create_modedb);
529 +EXPORT_SYMBOL(fb_get_monitor_limits);
530 diff --git a/drivers/video/vesafb-thread.c b/drivers/video/vesafb-thread.c
531 new file mode 100644
532 --- /dev/null
533 +++ b/drivers/video/vesafb-thread.c
534 @@ -0,0 +1,566 @@
535 +/*
536 + * Framebuffer driver for VBE 2.0+ compliant graphic boards - kernel thread
537 + * and vm86 routines.
538 + *
539 + * This code has to be compiled into the kernel even if vesafb is configured
540 + * as a module. If vesafb_thread were to be started while the module is being
541 + * initialized, it would share its active_mm with modprobe. This mm would be
542 + * lost after modprobe finished its work, and we can't allow it, because we
543 + * need it for as long as the vesafb thread is active.
544 + *
545 + * (c) 2004-2005 Michal Januszewski <spock@gentoo.org>
546 + *
547 + */
548 +
549 +#include <linux/workqueue.h>
550 +#include <linux/module.h>
551 +#include <linux/kernel.h>
552 +#include <linux/errno.h>
553 +#include <linux/mm.h>
554 +#include <linux/slab.h>
555 +#include <linux/delay.h>
556 +#include <linux/signal.h>
557 +#include <linux/suspend.h>
558 +#include <linux/unistd.h>
559 +#include <video/vesa.h>
560 +#include <video/edid.h>
561 +#include <asm/mman.h>
562 +#include <asm/page.h>
563 +#include <asm/vm86.h>
564 +#include <asm/thread_info.h>
565 +#include <asm/uaccess.h>
566 +#include "edid.h"
567 +
568 +#ifdef DEBUG
569 +#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
570 +#else
571 +#define DPRINTK(fmt, args...)
572 +#endif
573 +
574 +int vesafb_pid = 0;
575 +struct vm86_struct vm86;
576 +
577 +static DECLARE_MUTEX(vesafb_sem);
578 +static LIST_HEAD(vesafb_task_list);
579 +static DECLARE_WAIT_QUEUE_HEAD(vesafb_wait);
580 +
581 +_syscall3(int,ioperm,unsigned long, a, unsigned long, b, unsigned long, c);
582 +_syscall1(int,vm86old,struct vm86_struct __user*, v86);
583 +
584 +#define DEFAULT_VM86_FLAGS (IF_MASK | IOPL_MASK)
585 +#define VM86_PUSHW(x) vm86.regs.esp -= 2; *(unsigned short*)(real_mem+vm86.regs.esp) = x;
586 +#define REAL_MEM_SIZE 0x4000
587 +#define REAL_MEM 0x2000
588 +#define RET_CODE_SIZE 0x02
589 +#define STACK_SIZE 0x500
590 +#define BUFFER (STACK_SIZE + RET_CODE_SIZE)
591 +#define FLAG_D (1 << 10)
592 +
593 +/* segment prefix opcodes */
594 +enum {
595 + P_CS = 0x2e,
596 + P_SS = 0x36,
597 + P_DS = 0x3e,
598 + P_ES = 0x26,
599 + P_FS = 0x64,
600 + P_GS = 0x65
601 +};
602 +
603 +void vesafb_queue_task(struct vesafb_task *task)
604 +{
605 + list_add_tail(&task->node, &vesafb_task_list);
606 + wake_up(&vesafb_wait);
607 +}
608 +
609 +/* emulated vm86 ins instruction */
610 +static void vm86_ins(int size)
611 +{
612 + u32 edx, edi;
613 +
614 + edx = vm86.regs.edx & 0xffff;
615 + edi = (vm86.regs.edi & 0xffff) + (u32)(vm86.regs.es << 4);
616 +
617 + if (vm86.regs.eflags & FLAG_D)
618 + asm volatile ("std\n");
619 + else
620 + asm volatile ("cld\n");
621 +
622 + switch (size) {
623 + case 4: asm volatile ("insl\n" : "=D" (edi) : "d" (edx), "0" (edi)); break;
624 + case 2: asm volatile ("insw\n" : "=D" (edi) : "d" (edx), "0" (edi)); break;
625 + case 1: asm volatile ("insb\n" : "=D" (edi) : "d" (edx), "0" (edi));
626 + }
627 +
628 + if (vm86.regs.eflags & FLAG_D)
629 + asm volatile ("cld\n");
630 +
631 + edi -= (u32)(vm86.regs.es << 4);
632 +
633 + vm86.regs.edi &= 0xffff0000;
634 + vm86.regs.edi |= edi & 0xffff;
635 +}
636 +
637 +static void vm86_rep_ins(int size)
638 +{
639 + u16 cx = vm86.regs.ecx;
640 +
641 + while (cx--)
642 + vm86_ins(size);
643 +
644 + vm86.regs.ecx &= 0xffff0000;
645 +}
646 +
647 +/* emulated vm86 outs instruction */
648 +static void vm86_outs(int size, int segment)
649 +{
650 + u32 edx, esi, base;
651 +
652 + edx = vm86.regs.edx & 0xffff;
653 + esi = vm86.regs.esi & 0xffff;
654 +
655 + switch (segment) {
656 + case P_CS: base = vm86.regs.cs; break;
657 + case P_SS: base = vm86.regs.ss; break;
658 + case P_ES: base = vm86.regs.es; break;
659 + case P_FS: base = vm86.regs.fs; break;
660 + case P_GS: base = vm86.regs.gs; break;
661 + default: base = vm86.regs.ds; break;
662 + }
663 +
664 + esi += base << 4;
665 +
666 + if (vm86.regs.eflags & FLAG_D)
667 + asm volatile ("std\n");
668 + else
669 + asm volatile ("cld\n");
670 +
671 + switch (size) {
672 + case 4: asm volatile ("outsl\n" : "=S" (esi) : "d" (edx), "0" (esi)); break;
673 + case 2: asm volatile ("outsw\n" : "=S" (esi) : "d" (edx), "0" (esi)); break;
674 + case 1: asm volatile ("outsb\n" : "=S" (esi) : "d" (edx), "0" (esi)); break;
675 + }
676 +
677 + if (vm86.regs.eflags & FLAG_D)
678 + asm volatile ("cld");
679 +
680 + esi -= base << 4;
681 + vm86.regs.esi &= 0xffff0000;
682 + vm86.regs.esi |= (esi & 0xffff);
683 +}
684 +
685 +static void vm86_rep_outs(int size, int segment)
686 +{
687 + u16 cx = vm86.regs.ecx;
688 +
689 + while (cx--)
690 + vm86_outs(size, segment);
691 +
692 + vm86.regs.ecx &= 0xffff0000;
693 +}
694 +
695 +void vesafb_do_vm86(struct vm86_regs *regs)
696 +{
697 + unsigned char *real_mem = (void*)REAL_MEM;
698 + unsigned int ret;
699 +
700 + memset(&vm86,0,sizeof(vm86));
701 + memcpy(&vm86.regs, regs, sizeof(struct vm86_regs));
702 +
703 + /* the return code */
704 + real_mem[0] = 0xcd; /* int opcode */
705 + real_mem[1] = 0xff; /* int number (255) */
706 +
707 + /* we use int 255 to get back to protected mode */
708 + memset(&vm86.int_revectored, 0, sizeof(vm86.int_revectored));
709 + ((unsigned char *) &vm86.int_revectored)[0xff / 8] |= (1 << (0xff % 8)); /* int 0xff */
710 +
711 + /* it's up to the caller to set the rest of the registers */
712 + vm86.regs.eflags = DEFAULT_VM86_FLAGS;
713 + vm86.regs.cs = *(unsigned short *)0x42; /* 0x10 * 4 + 2 - the int map starts at 0x0 */
714 + vm86.regs.eip = *(unsigned short *)0x40; /* 0x10 * 4 */
715 +
716 + /* stack @ 0x10500, size: 0x500-4 - should be enough for our needs */
717 + vm86.regs.ss = (REAL_MEM >> 4);
718 + vm86.regs.esp = STACK_SIZE+RET_CODE_SIZE;
719 +
720 + /* these will be fetched off the stack when we come to an iret in the int's 0x10 code */
721 + VM86_PUSHW(DEFAULT_VM86_FLAGS);
722 + VM86_PUSHW((REAL_MEM >> 4)); /* return code segment */
723 + VM86_PUSHW(0x0000); /* return code offset */
724 +
725 + while(1) {
726 + ret = vm86old(&vm86);
727 +
728 + if (VM86_TYPE(ret) == VM86_INTx) {
729 +
730 + int vint = VM86_ARG(ret);
731 +
732 + /* if exit from vm86 was caused by int 0xff - we're done.. */
733 + if (vint == 0xff)
734 + goto vm86_done_call;
735 +
736 + /* .. otherwise, we have call the int handler manually */
737 + VM86_PUSHW(vm86.regs.eflags);
738 + VM86_PUSHW(vm86.regs.cs);
739 + VM86_PUSHW(vm86.regs.eip);
740 +
741 + vm86.regs.cs = *(unsigned short *)((vint << 2) + 2);
742 + vm86.regs.eip = *(unsigned short *)(vint << 2);
743 + vm86.regs.eflags &= ~(VIF_MASK | TF_MASK);
744 +
745 + } else if (VM86_TYPE(ret) == VM86_UNKNOWN) {
746 +
747 + u8 *instr;
748 + u8 data32 = 0, segment = P_DS, rep = 0;
749 + int i = 0;
750 +
751 + instr = (u8*)((vm86.regs.cs << 4) + vm86.regs.eip);
752 +
753 + while (1) {
754 +
755 + switch(instr[i]) {
756 +
757 + case 0x66: /* operand size prefix */
758 + data32 = 1 - data32;
759 + i++;
760 + break;
761 + case 0xf2: /* repnz */
762 + case 0xf3: /* rep */
763 + rep = 1;
764 + i++;
765 + break;
766 + case P_CS: /* segment prefix */
767 + case P_SS:
768 + case P_DS:
769 + case P_ES:
770 + case P_FS:
771 + case P_GS:
772 + segment = instr[i];
773 + i++;
774 + break;
775 + case 0xf0: /* LOCK - ignored */
776 + case 0x67: /* address size prefix - ignored */
777 + i++;
778 + break;
779 + case 0x6c: /* insb */
780 + if (rep) vm86_rep_ins(1);
781 + else vm86_ins(1);
782 + i++;
783 + goto vm86_done_emu;
784 + case 0x6d: /* insw / insd */
785 + if (rep)
786 + if (data32) vm86_rep_ins(4);
787 + else vm86_rep_ins(2);
788 + else
789 + if (data32) vm86_ins(4);
790 + else vm86_ins(2);
791 + i++;
792 + goto vm86_done_emu;
793 + case 0x6e: /* outsb */
794 + if (rep) vm86_rep_outs(1, segment);
795 + else vm86_outs(1, segment);
796 + i++;
797 + goto vm86_done_emu;
798 + case 0x6f: /* outsw / outsd */
799 + if (rep)
800 + if (data32) vm86_rep_outs(4, segment);
801 + else vm86_rep_outs(2, segment);
802 + else
803 + if (data32) vm86_outs(4, segment);
804 + else vm86_outs(2, segment);
805 + i++;
806 + goto vm86_done_emu;
807 + case 0xe4: /* inb xx */
808 + asm volatile (
809 + "inb %w1, %b0"
810 + : "=a" (vm86.regs.eax)
811 + : "d" (instr[i+1]), "0" (vm86.regs.eax));
812 + i += 2;
813 + goto vm86_done_emu;
814 + case 0xe5: /* inw xx / ind xx */
815 + if (data32)
816 + asm volatile (
817 + "inl %w1, %0"
818 + : "=a" (vm86.regs.eax)
819 + : "d" (instr[i+1]), "0" (vm86.regs.eax));
820 + else
821 + asm volatile (
822 + "inw %w1, %w0"
823 + : "=a" (vm86.regs.eax)
824 + : "d" (instr[i+1]), "0" (vm86.regs.eax));
825 + i += 2;
826 + goto vm86_done_emu;
827 + case 0xec: /* inb dx */
828 + asm volatile (
829 + "inb %w1, %b0"
830 + : "=a" (vm86.regs.eax)
831 + : "d" (vm86.regs.edx), "0" (vm86.regs.eax));
832 + i++;
833 + goto vm86_done_emu;
834 + case 0xed: /* inw dx / ind dx */
835 + if (data32)
836 + asm volatile (
837 + "inl %w1, %0"
838 + : "=a" (vm86.regs.eax)
839 + : "d" (vm86.regs.edx));
840 + else
841 + asm volatile (
842 + "inw %w1, %w0"
843 + : "=a" (vm86.regs.eax)
844 + : "d" (vm86.regs.edx));
845 + i++;
846 + goto vm86_done_emu;
847 + case 0xe6: /* outb xx */
848 + asm volatile (
849 + "outb %b0, %w1"
850 + : : "a" (vm86.regs.eax), "d" (instr[i+1]));
851 + i += 2;
852 + goto vm86_done_emu;
853 + case 0xe7: /* outw xx / outd xx */
854 + if (data32)
855 + asm volatile (
856 + "outl %0, %w1"
857 + : : "a" (vm86.regs.eax), "d" (instr[i+1]));
858 + else
859 + asm volatile (
860 + "outw %w0, %w1"
861 + : : "a" (vm86.regs.eax), "d" (instr[i+1]));
862 + i += 2;
863 + goto vm86_done_emu;
864 + case 0xee: /* outb dx */
865 + asm volatile (
866 + "outb %b0, %w1"
867 + : : "a" (vm86.regs.eax), "d" (vm86.regs.edx));
868 + i++;
869 + goto vm86_done_emu;
870 + case 0xef: /* outw dx / outd dx */
871 + if (data32)
872 + asm volatile (
873 + "outl %0, %w1"
874 + : : "a" (vm86.regs.eax), "d" (vm86.regs.edx));
875 + else
876 + asm volatile (
877 + "outw %w0, %w1"
878 + : : "a" (vm86.regs.eax), "d" (vm86.regs.edx));
879 + i++;
880 + goto vm86_done_emu;
881 + default:
882 + printk(KERN_ERR "vesafb: BUG, opcode %x emulation not supported\n", instr[i]);
883 + goto vm86_done_call;
884 + }
885 + }
886 +vm86_done_emu: vm86.regs.eip += i;
887 + } else {
888 + printk(KERN_ERR "vesafb: BUG, returned from vm86 with %x\n", ret);
889 + goto vm86_done_call;
890 + }
891 + }
892 +
893 +vm86_done_call:
894 +
895 + /* copy the registers' state back to the caller's struct */
896 + memcpy(regs, &vm86.regs, sizeof(struct vm86_regs));
897 +}
898 +
899 +#define vesafb_get_string(str) { \
900 + \
901 + /* the address is in the form ssssoooo, where oooo = offset, ssss = segment */ \
902 + addr = ((vbe_pib(task->res)->str & 0xffff0000) >> 12) + \
903 + (vbe_pib(task->res)->str & 0x0000ffff); \
904 + \
905 + /* the data is in ROM which is shared between processes, so we just translate the \
906 + real mode address into one visible from the kernel space */ \
907 + if (addr >= 0xa0000) { \
908 + vbe_pib(task->res)->str = (u32) __va(addr); \
909 + \
910 + /* the data is in the buffer, we just have to convert the address so that it would \
911 + point into the buffer user provided */ \
912 + } else if (addr > REAL_MEM+BUFFER && addr < REAL_MEM+BUFFER + \
913 + sizeof(struct vesafb_vbe_info_block)) { \
914 + addr -= BUFFER+REAL_MEM; \
915 + vbe_pib(task->res)->str = (u32) (task->res + addr); \
916 + \
917 + /* this should never happen: someone was insane enough to put the data somewhere in the RAM */ \
918 + } else { \
919 + vbe_pib(task->res)->str = (u32) ""; \
920 + } \
921 +}
922 +
923 +void vesafb_handle_tasks(void)
924 +{
925 + struct vesafb_task *task;
926 + struct list_head *node, *next;
927 + int addr, res;
928 +
929 + down(&vesafb_sem);
930 + list_for_each_safe(node, next, &vesafb_task_list) {
931 +
932 + task = container_of(node, struct vesafb_task, node);
933 +
934 + switch (task->type) {
935 +
936 + case VESAFB_TASK_DOVM86:
937 + vesafb_do_vm86(&task->regs);
938 + break;
939 +
940 + case VESAFB_TASK_GETVBE_IB:
941 + task->regs.es = (REAL_MEM >> 4);
942 + task->regs.edi = BUFFER;
943 + strncpy(vbe_pib(REAL_MEM+BUFFER)->vbe_signature,"VBE2",4);
944 +
945 + vesafb_do_vm86(&task->regs);
946 +
947 + memcpy(task->res, (void*)(REAL_MEM + BUFFER), sizeof(struct vesafb_vbe_info_block));
948 +
949 + /* the OEM fields were not defined prior to VBE 2.0 */
950 + if (vbe_pib(task->res)->vbe_version >= 0x200) {
951 + vesafb_get_string(oem_string_ptr);
952 + vesafb_get_string(oem_vendor_name_ptr);
953 + vesafb_get_string(oem_product_name_ptr);
954 + vesafb_get_string(oem_product_rev_ptr);
955 + }
956 +
957 + /* this is basically the same as vesafb_get_string */
958 + addr = ((vbe_pib(task->res)->mode_list_ptr & 0xffff0000) >> 12) +
959 + (vbe_pib(task->res)->mode_list_ptr & 0x0000ffff);
960 +
961 + if (addr >= 0xa0000) {
962 + vbe_pib(task->res)->mode_list_ptr = (u32) __va(addr);
963 + } else if (addr > REAL_MEM+BUFFER && addr < REAL_MEM+BUFFER +
964 + sizeof(struct vesafb_vbe_info_block))
965 + {
966 + addr -= BUFFER+REAL_MEM;
967 + vbe_pib(task->res)->mode_list_ptr = (u32) (task->res + addr);
968 + } else {
969 + res = 0;
970 + printk(KERN_WARNING "vesafb: warning, copying modelist from somewhere in RAM!\n");
971 + while (*(u16*)(addr+res) != 0xffff &&
972 + res < (sizeof(vbe_pib(task->res)->reserved) - 2) )
973 + {
974 + *(u16*) ((u32)&(vbe_pib(task->res)->reserved) + res) =
975 + *(u16*)(addr+res);
976 + res += 2;
977 + }
978 +
979 + *(u16*) ((u32)&(vbe_pib(task->res)->reserved) + res) = 0xffff;
980 + }
981 + break;
982 +
983 + case VESAFB_TASK_GETVBE_MODEINFO:
984 + task->regs.es = (REAL_MEM >> 4);
985 + task->regs.edi = BUFFER;
986 + vesafb_do_vm86(&task->regs);
987 + memcpy(task->res, (void*)(REAL_MEM + BUFFER), sizeof(struct vesafb_mode_info_block));
988 + break;
989 +
990 + case VESAFB_TASK_SWITCHMODE:
991 + if (task->res != NULL) {
992 + task->regs.es = (REAL_MEM >> 4);
993 + task->regs.edi = BUFFER;
994 + memcpy((void*)(REAL_MEM + BUFFER), task->res, sizeof(struct vesafb_crtc_info_block));
995 + }
996 +
997 + vesafb_do_vm86(&task->regs);
998 + break;
999 +
1000 + case VESAFB_TASK_SETPAL:
1001 + task->regs.es = (REAL_MEM >> 4);
1002 + task->regs.edi = BUFFER;
1003 + memcpy((void*)(REAL_MEM + BUFFER), task->res, sizeof(struct vesafb_pal_entry));
1004 + vesafb_do_vm86(&task->regs);
1005 + break;
1006 +
1007 + case VESAFB_TASK_GETEDID:
1008 + task->regs.es = (REAL_MEM >> 4);
1009 + task->regs.edi = BUFFER;
1010 + vesafb_do_vm86(&task->regs);
1011 + memcpy(task->res, (void*)(REAL_MEM + BUFFER), EDID_LENGTH);
1012 +
1013 + default:
1014 + break;
1015 + }
1016 +
1017 + task->done = 1;
1018 + if (task->flags & VESAFB_FLAG_FREESTRUCT) {
1019 + kfree(task);
1020 + }
1021 + }
1022 +
1023 + up(&vesafb_sem);
1024 + list_del_init(node);
1025 +}
1026 +
1027 +int vesafb_thread(void *unused)
1028 +{
1029 + struct vm_area_struct vma;
1030 + struct page *page;
1031 +
1032 + int ret, err = 0;
1033 + void *mem;
1034 +
1035 + set_fs(KERNEL_DS);
1036 + daemonize("vesafb");
1037 + DPRINTK("started vesafb thread\n");
1038 +
1039 + current->mm = current->active_mm;
1040 + mem = kmalloc(REAL_MEM_SIZE,GFP_KERNEL);
1041 +
1042 + if (!mem)
1043 + return -ENOMEM;
1044 +
1045 + for (page = virt_to_page(mem); page < virt_to_page(mem+REAL_MEM_SIZE); page++) {
1046 + SetPageReserved(page);
1047 + }
1048 +
1049 +#ifdef CONFIG_SMP
1050 + cpus_clear(current->active_mm->cpu_vm_mask);
1051 + cpu_set(smp_processor_id(), current->active_mm->cpu_vm_mask);
1052 +#endif
1053 +
1054 + vma.vm_mm = current->active_mm;
1055 + vma.vm_page_prot.pgprot = PROT_READ | PROT_EXEC | PROT_WRITE;
1056 +
1057 + ret = io_remap_page_range(&vma, 0x000000, __pa(mem), REAL_MEM_SIZE, vma.vm_page_prot);
1058 + ret += io_remap_page_range(&vma, 0x0a0000, 0x0a0000, 0x100000 - 0x0a0000, vma.vm_page_prot);
1059 +
1060 + if (ret) {
1061 + printk(KERN_ERR "vesafb thread: memory remapping failed\n");
1062 + err = -EINVAL;
1063 + goto thr_end;
1064 + }
1065 +
1066 + /* copy the first 0x20000 bytes from low mem to our private memory, which is
1067 + * then used for the vm86 calls */
1068 + memcpy((void*)0x0, __va(0x0), REAL_MEM_SIZE);
1069 +
1070 + ioperm(0,1024,1); /* we can live if it fails, so don't bother checking for errors */
1071 + set_user_nice(current, -10);
1072 +
1073 + while (1) {
1074 + vesafb_handle_tasks();
1075 + wait_event_interruptible(vesafb_wait, !list_empty(&vesafb_task_list));
1076 + try_to_freeze();
1077 + if (signal_pending(current))
1078 + break;
1079 + }
1080 +
1081 +thr_end:
1082 + DPRINTK("exiting the vesafb thread\n");
1083 + vesafb_pid = 0;
1084 +
1085 + for (page = virt_to_page(mem); page < virt_to_page(mem+REAL_MEM_SIZE); page++) {
1086 + ClearPageReserved(page);
1087 + }
1088 +
1089 + kfree(mem);
1090 + return err;
1091 +}
1092 +
1093 +int vesafb_init_thread(void)
1094 +{
1095 + vesafb_pid = kernel_thread(vesafb_thread,NULL,0);
1096 + return 0;
1097 +}
1098 +
1099 +EXPORT_SYMBOL(vesafb_pid);
1100 +EXPORT_SYMBOL(vesafb_queue_task);
1101 diff --git a/drivers/video/vesafb-tng.c b/drivers/video/vesafb-tng.c
1102 new file mode 100644
1103 --- /dev/null
1104 +++ b/drivers/video/vesafb-tng.c
1105 @@ -0,0 +1,1243 @@
1106 +/*
1107 + * Framebuffer driver for VBE 2.0+ compliant graphic boards
1108 + *
1109 + * (c) 2004-2005 Michal Januszewski <spock@gentoo.org>
1110 + * Based upon vesafb code by Gerd Knorr <kraxel@goldbach.in-berlin.de>
1111 + *
1112 + */
1113 +
1114 +#ifdef DEBUG
1115 +#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
1116 +#else
1117 +#define DPRINTK(fmt, args...)
1118 +#endif
1119 +
1120 +#include <linux/module.h>
1121 +#include <linux/kernel.h>
1122 +#include <linux/errno.h>
1123 +#include <linux/string.h>
1124 +#include <linux/mm.h>
1125 +#include <linux/tty.h>
1126 +#include <linux/delay.h>
1127 +#include <linux/fb.h>
1128 +#include <linux/ioport.h>
1129 +#include <linux/init.h>
1130 +#include <linux/proc_fs.h>
1131 +#include <video/edid.h>
1132 +#include <video/vesa.h>
1133 +
1134 +#include <asm/io.h>
1135 +#include <asm/mtrr.h>
1136 +#include <asm/page.h>
1137 +#include <asm/pgtable.h>
1138 +#include "edid.h"
1139 +
1140 +#define dac_reg (0x3c8)
1141 +#define dac_val (0x3c9)
1142 +
1143 +#define VESAFB_NEED_EXACT_RES 1
1144 +#define VESAFB_NEED_EXACT_DEPTH 2
1145 +
1146 +/* --------------------------------------------------------------------- */
1147 +
1148 +static struct fb_var_screeninfo vesafb_defined __initdata = {
1149 + .activate = FB_ACTIVATE_NOW,
1150 + .height = -1,
1151 + .width = -1,
1152 + .right_margin = 32,
1153 + .upper_margin = 16,
1154 + .lower_margin = 4,
1155 + .vsync_len = 4,
1156 + .vmode = FB_VMODE_NONINTERLACED,
1157 +};
1158 +
1159 +static struct fb_fix_screeninfo vesafb_fix __initdata = {
1160 + .id = "VESA VGA",
1161 + .type = FB_TYPE_PACKED_PIXELS,
1162 + .accel = FB_ACCEL_NONE,
1163 +};
1164 +
1165 +static int mtrr = 1; /* use MTRR */
1166 +static int ypan = 0; /* 0 - nothing, 1 - ypan, 2 -ywrap */
1167 +static int pmi_setpal = 0; /* pmi for palette changes */
1168 +static unsigned short *pmi_base = NULL; /* protected mode interface location in memory */
1169 +static void (*pmi_start)(void) = NULL;
1170 +static void (*pmi_pal)(void) = NULL;
1171 +static struct task_struct *vesafb_serv_thread = NULL;
1172 +static struct vesafb_vbe_info_block vbe_ib;
1173 +static struct vesafb_mode_info_block *vbe_modes;
1174 +static int vbe_modes_cnt = 0;
1175 +static u8 mon_limits = 0; /* 0 - no monitor limits, 1 - full monitor limits,
1176 + 2 - monitor limits with default pixel clock */
1177 +static int nocrtc = 0; /* ignore CRTC settings */
1178 +static struct fb_info *vesafb_info = NULL;
1179 +static struct fb_videomode *edid_modes __initdata = NULL;
1180 +static int edid_modes_cnt __initdata = 0;
1181 +static int noedid __initdata = 0; /* don't try the DDC transfers */
1182 +static int vram_remap __initdata = 0; /* set amount of memory to be used */
1183 +static int vram_total __initdata = 0; /* set total amount of memory */
1184 +static unsigned short maxclk __initdata = 0; /* maximum pixel clock */
1185 +static unsigned short maxvf __initdata = 0; /* maximum vertical frequency */
1186 +static unsigned short maxhf __initdata = 0; /* maximum horizontal frequency */
1187 +static int gtf __initdata = 0; /* forces use of the GTF */
1188 +static char *mode_option __initdata = NULL;
1189 +static unsigned short vbemode = 0;
1190 +
1191 +extern int vesafb_pid; /* PID of the vesafb service thread */
1192 +
1193 +/* --------------------------------------------------------------------- */
1194 +
1195 +#define vesafb_create_task(task) { task = kmalloc(sizeof(struct vesafb_task), GFP_ATOMIC); \
1196 + if (task) memset(task,0,sizeof(struct vesafb_task)); }
1197 +
1198 +#define vesafb_wait_for_task(task) { while (task->done == 0) { schedule(); } }
1199 +
1200 +extern void vesafb_queue_task(struct vesafb_task *task);
1201 +static int vesafb_find_vbe_mode(int xres, int yres, int bpp, unsigned char flags);
1202 +
1203 +struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize);
1204 +int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs);
1205 +
1206 +/* --------------------------------------------------------------------- */
1207 +
1208 +static int vesafb_pan_display(struct fb_var_screeninfo *var,
1209 + struct fb_info *info)
1210 +{
1211 +#ifdef __i386__
1212 + int offset;
1213 +
1214 + if (!ypan)
1215 + return -EINVAL;
1216 + if (var->xoffset)
1217 + return -EINVAL;
1218 + if (var->yoffset > var->yres_virtual)
1219 + return -EINVAL;
1220 + if ((ypan==1) && var->yoffset+var->yres > var->yres_virtual)
1221 + return -EINVAL;
1222 +
1223 + offset = (var->yoffset * info->fix.line_length + var->xoffset) / 4;
1224 +
1225 + /* It turns out it's not the best idea to do panning via vm86,
1226 + * so we only allow it if we have a PMI. */
1227 + if (pmi_start) {
1228 + __asm__ __volatile__(
1229 + "call *(%%edi)"
1230 + : /* no return value */
1231 + : "a" (0x4f07), /* EAX */
1232 + "b" (0), /* EBX */
1233 + "c" (offset), /* ECX */
1234 + "d" (offset >> 16), /* EDX */
1235 + "D" (&pmi_start)); /* EDI */
1236 + }
1237 +#endif
1238 + return 0;
1239 +}
1240 +
1241 +static void vesa_setpalette(int regno, unsigned red, unsigned green, unsigned blue, int shift)
1242 +{
1243 + struct vesafb_pal_entry entry;
1244 + struct vesafb_task *mytask;
1245 +
1246 +#ifdef __i386__
1247 + entry.red = red >> shift;
1248 + entry.green = green >> shift;
1249 + entry.blue = blue >> shift;
1250 + entry.pad = 0;
1251 +
1252 + if (pmi_setpal) {
1253 + __asm__ __volatile__(
1254 + "call *(%%esi)"
1255 + : /* no return value */
1256 + : "a" (0x4f09), /* EAX */
1257 + "b" (0), /* EBX */
1258 + "c" (1), /* ECX */
1259 + "d" (regno), /* EDX */
1260 + "D" (&entry), /* EDI */
1261 + "S" (&pmi_pal)); /* ESI */
1262 + } else {
1263 + vesafb_create_task (mytask);
1264 +
1265 + mytask->regs.eax = 0x4f09;
1266 + mytask->regs.ebx = 0x0;
1267 + mytask->regs.ecx = 1;
1268 + mytask->regs.edx = regno;
1269 + mytask->res = &entry;
1270 + mytask->type = VESAFB_TASK_SETPAL;
1271 +
1272 + vesafb_queue_task (mytask);
1273 + vesafb_wait_for_task(mytask);
1274 + kfree(mytask);
1275 + }
1276 +#endif
1277 +}
1278 +
1279 +static int vesafb_setcolreg(unsigned regno, unsigned red, unsigned green,
1280 + unsigned blue, unsigned transp,
1281 + struct fb_info *info)
1282 +{
1283 + /*
1284 + * Set a single color register. The values supplied are
1285 + * already rounded down to the hardware's capabilities
1286 + * (according to the entries in the `var' structure). Return
1287 + * != 0 for invalid regno.
1288 + */
1289 + if (regno >= info->cmap.len)
1290 + return 1;
1291 +
1292 + switch (info->var.bits_per_pixel) {
1293 + case 8:
1294 + vesa_setpalette(regno,red,green,blue,16 - info->var.green.length);
1295 + break;
1296 + case 16:
1297 + if (info->var.red.offset == 10) {
1298 + /* 1:5:5:5 */
1299 + ((u32*) (info->pseudo_palette))[regno] =
1300 + ((red & 0xf800) >> 1) |
1301 + ((green & 0xf800) >> 6) |
1302 + ((blue & 0xf800) >> 11);
1303 + } else {
1304 + /* 0:5:6:5 */
1305 + ((u32*) (info->pseudo_palette))[regno] =
1306 + ((red & 0xf800) ) |
1307 + ((green & 0xfc00) >> 5) |
1308 + ((blue & 0xf800) >> 11);
1309 + }
1310 + break;
1311 + case 24:
1312 + red >>= 8;
1313 + green >>= 8;
1314 + blue >>= 8;
1315 + ((u32 *)(info->pseudo_palette))[regno] =
1316 + (red << info->var.red.offset) |
1317 + (green << info->var.green.offset) |
1318 + (blue << info->var.blue.offset);
1319 + break;
1320 + case 32:
1321 + red >>= 8;
1322 + green >>= 8;
1323 + blue >>= 8;
1324 + ((u32 *)(info->pseudo_palette))[regno] =
1325 + (red << info->var.red.offset) |
1326 + (green << info->var.green.offset) |
1327 + (blue << info->var.blue.offset);
1328 + break;
1329 + }
1330 + return 0;
1331 +}
1332 +
1333 +static int vesafb_set_par(struct fb_info *info)
1334 +{
1335 + struct vesafb_par *par = (struct vesafb_par *) info->par;
1336 + struct vesafb_task *mytask;
1337 + struct vesafb_crtc_info_block *crtc = NULL;
1338 + struct vesafb_mode_info_block *mode = NULL;
1339 + int err = 0, i;
1340 +
1341 + /* Has the VBE mode number been specified? */
1342 + if (vbemode > 0) {
1343 + for (i = 0; i < vbe_modes_cnt; i++) {
1344 + if (vbe_modes[i].mode_id == vbemode) {
1345 + mode = &vbe_modes[i];
1346 + break;
1347 + }
1348 + }
1349 + } else {
1350 + i = vesafb_find_vbe_mode(info->var.xres, info->var.yres,
1351 + info->var.bits_per_pixel, VESAFB_NEED_EXACT_RES | VESAFB_NEED_EXACT_DEPTH);
1352 + if (i > 0)
1353 + mode = &vbe_modes[i];
1354 + }
1355 +
1356 + if (mode == NULL)
1357 + return -EINVAL;
1358 +
1359 + vesafb_create_task (mytask);
1360 +
1361 + mytask->regs.eax = 0x4f02;
1362 + mytask->regs.ebx = mode->mode_id | 0x4000; /* use LFB */
1363 +
1364 + if (vbe_ib.vbe_version >= 0x0300 && !nocrtc && !vbemode) {
1365 +
1366 + mytask->regs.ebx |= 0x0800; /* use CRTC data */
1367 + crtc = kmalloc(sizeof(struct vesafb_crtc_info_block), GFP_KERNEL);
1368 +
1369 + if (!crtc) {
1370 + err = -ENOMEM;
1371 + goto out;
1372 + }
1373 + crtc->horiz_start = info->var.xres + info->var.right_margin;
1374 + crtc->horiz_end = crtc->horiz_start + info->var.hsync_len;
1375 + crtc->horiz_total = crtc->horiz_end + info->var.left_margin;
1376 +
1377 + crtc->vert_start = info->var.yres + info->var.lower_margin;
1378 + crtc->vert_end = crtc->vert_start + info->var.vsync_len;
1379 + crtc->vert_total = crtc->vert_end + info->var.upper_margin;
1380 +
1381 + crtc->pixel_clock = PICOS2KHZ(info->var.pixclock) * 1000;
1382 + crtc->refresh_rate = (u16)(100 * (crtc->pixel_clock / (crtc->vert_total * crtc->horiz_total)));
1383 + crtc->flags = 0;
1384 +
1385 + if (info->var.vmode & FB_VMODE_DOUBLE)
1386 + crtc->flags |= 0x1;
1387 +
1388 + if (info->var.vmode & FB_VMODE_INTERLACED)
1389 + crtc->flags |= 0x2;
1390 +
1391 + if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
1392 + crtc->flags |= 0x4;
1393 +
1394 + if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
1395 + crtc->flags |= 0x8;
1396 +
1397 + memcpy(&par->crtc, crtc, sizeof(struct vesafb_crtc_info_block));
1398 + } else
1399 + memset(&par->crtc, 0, sizeof(struct vesafb_crtc_info_block));
1400 +
1401 + mytask->res = (void*)crtc;
1402 + mytask->type = VESAFB_TASK_SWITCHMODE;
1403 +
1404 + vesafb_queue_task (mytask);
1405 + vesafb_wait_for_task(mytask);
1406 +
1407 + if ((mytask->regs.eax & 0xffff) != 0x004f) {
1408 + printk(KERN_ERR "vesafb: mode switch failed (eax: 0x%lx)\n", mytask->regs.eax);
1409 + err = -EINVAL;
1410 + goto out;
1411 + }
1412 +
1413 + /* The VBE mode number is valid only the first time the mode is set. */
1414 + if (vbemode)
1415 + vbemode = 0;
1416 +
1417 + if (vbe_ib.capabilities & VESAFB_CAP_CAN_SWITCH_DAC && mode->bits_per_pixel <= 8) {
1418 + mytask->done = 0;
1419 + mytask->type = VESAFB_TASK_DOVM86;
1420 + mytask->regs.eax = 0x4f08;
1421 + mytask->regs.ebx = 0x0800;
1422 +
1423 + vesafb_queue_task (mytask);
1424 + vesafb_wait_for_task(mytask);
1425 +
1426 + if ((mytask->regs.eax & 0xffff) != 0x004f ||
1427 + ((mytask->regs.ebx & 0xff00) >> 8) != 8) {
1428 + /* We've failed to set the DAC palette format - time to correct var. */
1429 + info->var.red.length = 6;
1430 + info->var.green.length = 6;
1431 + info->var.blue.length = 6;
1432 + }
1433 + }
1434 +
1435 + info->fix.visual = (info->var.bits_per_pixel == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
1436 + info->fix.line_length = mode->bytes_per_scan_line;
1437 + par->vbe_mode = mode->mode_id;
1438 +
1439 + DPRINTK("set new mode %dx%d-%d (0x%x)\n", info->var.xres, info->var.yres, info->var.bits_per_pixel, mode->mode_id);
1440 +
1441 +out: if (crtc != NULL)
1442 + kfree(crtc);
1443 + kfree(mytask);
1444 +
1445 + return err;
1446 +}
1447 +
1448 +static void vesafb_setup_var(struct fb_var_screeninfo *var, struct fb_info *info,
1449 + struct vesafb_mode_info_block *mode)
1450 +{
1451 + var->xres = mode->x_res;
1452 + var->yres = mode->y_res;
1453 + var->xres_virtual = mode->x_res;
1454 + var->yres_virtual = (ypan) ? info->fix.smem_len / mode->bytes_per_scan_line : mode->y_res;
1455 + var->xoffset = 0;
1456 + var->yoffset = 0;
1457 + var->bits_per_pixel = mode->bits_per_pixel;
1458 +
1459 + if (var->bits_per_pixel == 15)
1460 + var->bits_per_pixel = 16;
1461 +
1462 + if (var->bits_per_pixel > 8) {
1463 + var->red.offset = mode->red_off;
1464 + var->red.length = mode->red_len;
1465 + var->green.offset = mode->green_off;
1466 + var->green.length = mode->green_len;
1467 + var->blue.offset = mode->blue_off;
1468 + var->blue.length = mode->blue_len;
1469 + var->transp.offset = mode->rsvd_off;
1470 + var->transp.length = mode->rsvd_len;
1471 +
1472 + DPRINTK("directcolor: size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
1473 + mode->rsvd_len,
1474 + mode->red_len,
1475 + mode->green_len,
1476 + mode->blue_len,
1477 + mode->rsvd_off,
1478 + mode->red_off,
1479 + mode->green_off,
1480 + mode->blue_off);
1481 + } else {
1482 + var->red.offset = 0;
1483 + var->green.offset = 0;
1484 + var->blue.offset = 0;
1485 + var->transp.offset = 0;
1486 +
1487 + /* We're assuming that we can switch the DAC to 8 bits. If this proves
1488 + * to be incorrect, we'll update the fields later in set_par. */
1489 + if (vbe_ib.capabilities & VESAFB_CAP_CAN_SWITCH_DAC) {
1490 + var->red.length = 8;
1491 + var->green.length = 8;
1492 + var->blue.length = 8;
1493 + var->transp.length = 0;
1494 + } else {
1495 + var->red.length = 6;
1496 + var->green.length = 6;
1497 + var->blue.length = 6;
1498 + var->transp.length = 0;
1499 + }
1500 + }
1501 +}
1502 +
1503 +static int inline vesafb_check_limits(struct fb_var_screeninfo *var, struct fb_info *info)
1504 +{
1505 + if (mon_limits)
1506 + return fb_validate_mode(var, info);
1507 + else
1508 + return 0;
1509 +}
1510 +
1511 +static int vesafb_find_vbe_mode(int xres, int yres, int bpp, unsigned char flags)
1512 +{
1513 + int i, match = -1, h = 0, d = 0x7fffffff;
1514 +
1515 + for (i = 0; i < vbe_modes_cnt; i++) {
1516 +
1517 + h = abs(vbe_modes[i].x_res - xres) + abs(vbe_modes[i].y_res - yres) +
1518 + abs(bpp - vbe_modes[i].bits_per_pixel);
1519 +
1520 + if (h == 0)
1521 + return i;
1522 +
1523 + if (h < d || (h == d && vbe_modes[i].bits_per_pixel > bpp)) {
1524 + d = h;
1525 + match = i;
1526 + }
1527 + }
1528 +
1529 + i = 1;
1530 +
1531 + if (flags & VESAFB_NEED_EXACT_RES && d > 24)
1532 + i = 0;
1533 +
1534 + if (flags & VESAFB_NEED_EXACT_DEPTH && d > 1)
1535 + i = 0;
1536 +
1537 + if (i != 0)
1538 + return match;
1539 + else
1540 + return -1;
1541 +}
1542 +
1543 +static int vesafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1544 +{
1545 + int match = -1;
1546 +
1547 + if (vesafb_check_limits(var, info))
1548 + return -EINVAL;
1549 +
1550 + /* FIXME: we should allow interlaced/double modes if an appropriate mode is supported by the VBE */
1551 + if (var->vmode & (FB_VMODE_INTERLACED | FB_VMODE_DOUBLE))
1552 + return -EINVAL;
1553 +
1554 + match = vesafb_find_vbe_mode(var->xres, var->yres, var->bits_per_pixel, VESAFB_NEED_EXACT_RES);
1555 +
1556 + if (match == -1) {
1557 + DPRINTK("vesafb: mode %dx%d-%d not found\n", var->xres, var->yres,
1558 + var->bits_per_pixel);
1559 + return -EINVAL;
1560 + } else {
1561 + var->bits_per_pixel = vbe_modes[match].bits_per_pixel;
1562 + vesafb_setup_var(var, info, &vbe_modes[match]);
1563 +
1564 + DPRINTK("found mode 0x%x (%dx%d-%dbpp)\n",
1565 + vbe_modes[match].mode_id, vbe_modes[match].x_res, vbe_modes[match].y_res,
1566 + vbe_modes[match].bits_per_pixel);
1567 + }
1568 +
1569 + /* Check whether we have remapped enough memory for this mode.. */
1570 + if (var->yres * vbe_modes[match].bytes_per_scan_line > info->fix.smem_len) {
1571 + return -EINVAL;
1572 + }
1573 +
1574 + return 0;
1575 +}
1576 +
1577 +static void vesafb_platform_release(struct device *device)
1578 +{
1579 + return;
1580 +}
1581 +
1582 +static int __init vesafb_probe(struct device *device);
1583 +
1584 +static struct fb_ops vesafb_ops = {
1585 + .owner = THIS_MODULE,
1586 + .fb_setcolreg = vesafb_setcolreg,
1587 + .fb_pan_display = vesafb_pan_display,
1588 + .fb_fillrect = cfb_fillrect,
1589 + .fb_copyarea = cfb_copyarea,
1590 + .fb_imageblit = cfb_imageblit,
1591 + .fb_cursor = soft_cursor,
1592 + .fb_check_var = vesafb_check_var,
1593 + .fb_set_par = vesafb_set_par
1594 +};
1595 +
1596 +static struct device_driver vesafb_driver = {
1597 + .name = "vesafb",
1598 + .bus = &platform_bus_type,
1599 + .probe = vesafb_probe,
1600 +};
1601 +
1602 +static struct platform_device vesafb_device = {
1603 + .name = "vesafb",
1604 + .dev = {
1605 + .release = vesafb_platform_release,
1606 + }
1607 +};
1608 +
1609 +#ifndef MODULE
1610 +int __init vesafb_setup(char *options)
1611 +{
1612 + char *this_opt;
1613 +
1614 + if (!options || !*options)
1615 + return 0;
1616 +
1617 + DPRINTK("options %s\n",options);
1618 +
1619 + while ((this_opt = strsep(&options, ",")) != NULL) {
1620 + if (!*this_opt) continue;
1621 +
1622 + DPRINTK("this_opt: %s\n",this_opt);
1623 +
1624 + if (! strcmp(this_opt, "redraw"))
1625 + ypan=0;
1626 + else if (! strcmp(this_opt, "ypan"))
1627 + ypan=1;
1628 + else if (! strcmp(this_opt, "ywrap"))
1629 + ypan=2;
1630 + else if (! strcmp(this_opt, "vgapal"))
1631 + pmi_setpal=0;
1632 + else if (! strcmp(this_opt, "pmipal"))
1633 + pmi_setpal=1;
1634 + else if (! strcmp(this_opt, "mtrr"))
1635 + mtrr=1;
1636 + else if (! strcmp(this_opt, "nomtrr"))
1637 + mtrr=0;
1638 + else if (! strcmp(this_opt, "nocrtc"))
1639 + nocrtc=1;
1640 + else if (! strcmp(this_opt, "noedid"))
1641 + noedid=1;
1642 + else if (! strcmp(this_opt, "gtf"))
1643 + gtf=1;
1644 + else if (! strncmp(this_opt, "vtotal:", 7))
1645 + vram_total = simple_strtoul(this_opt+7, NULL, 0);
1646 + else if (! strncmp(this_opt, "vremap:", 7))
1647 + vram_remap = simple_strtoul(this_opt+7, NULL, 0);
1648 + else if (! strncmp(this_opt, "maxhf:", 6))
1649 + maxhf = simple_strtoul(this_opt + 6, NULL, 0);
1650 + else if (! strncmp(this_opt, "maxvf:", 6))
1651 + maxvf = simple_strtoul(this_opt + 6, NULL, 0);
1652 + else if (! strncmp(this_opt, "maxclk:", 7))
1653 + maxclk = simple_strtoul(this_opt + 7, NULL, 0);
1654 + else if (! strncmp(this_opt, "vbemode:", 8))
1655 + vbemode = simple_strtoul(this_opt + 8, NULL,0);
1656 + else if (this_opt[0] >= '0' && this_opt[0] <= '9') {
1657 + DPRINTK("mode_option: %s\n",this_opt);
1658 + mode_option = this_opt;
1659 + } else {
1660 + printk(KERN_WARNING "vesafb: unrecognized option %s\n", this_opt);
1661 + }
1662 + }
1663 +
1664 + return 0;
1665 +}
1666 +#endif /* !MODULE */
1667 +
1668 +static int vesafb_read_proc_modes(char *buf, char **start, off_t offset,
1669 + int len, int *eof, void *private)
1670 +{
1671 + int clen = 0, i;
1672 +
1673 + for (i = 0; i < vbe_modes_cnt; i++) {
1674 + clen += sprintf(buf + clen, "%dx%d-%d\n", vbe_modes[i].x_res,
1675 + vbe_modes[i].y_res, vbe_modes[i].bits_per_pixel);
1676 + }
1677 + *start = buf + offset;
1678 +
1679 + if (clen > offset) {
1680 + clen -= offset;
1681 + } else {
1682 + clen = 0;
1683 + }
1684 + return clen;
1685 +}
1686 +
1687 +static int vesafb_read_proc_vbe_info(char *buf, char **start, off_t offset,
1688 + int len, int *eof, void *private)
1689 +{
1690 + int clen = 0;
1691 +
1692 + clen += sprintf(buf + clen, "Version: %d.%d\n", ((vbe_ib.vbe_version & 0xff00) >> 8), vbe_ib.vbe_version & 0xff);
1693 + clen += sprintf(buf + clen, "Vendor: %s\n", (char*)vbe_ib.oem_vendor_name_ptr);
1694 + clen += sprintf(buf + clen, "Product: %s\n", (char*)vbe_ib.oem_product_name_ptr);
1695 + clen += sprintf(buf + clen, "OEM rev: %s\n", (char*)vbe_ib.oem_product_rev_ptr);
1696 + clen += sprintf(buf + clen, "OEM string: %s\n", (char*)vbe_ib.oem_string_ptr);
1697 +
1698 + *start = buf + offset;
1699 +
1700 + if (clen > offset) {
1701 + clen -= offset;
1702 + } else {
1703 + clen = 0;
1704 + }
1705 + return clen;
1706 +}
1707 +
1708 +static int __init vesafb_vbe_init(struct fb_info *info)
1709 +{
1710 + struct vesafb_task *mytask;
1711 + u16 *mode = 0;
1712 + int i, off = 0;
1713 +
1714 + vesafb_create_task (mytask);
1715 + mytask->regs.eax = 0x4f00;
1716 + mytask->type = VESAFB_TASK_GETVBE_IB;
1717 + mytask->res = &vbe_ib;
1718 + vesafb_queue_task (mytask);
1719 + vesafb_wait_for_task(mytask);
1720 +
1721 + if (vbe_ib.vbe_version < 0x0200) {
1722 + printk(KERN_ERR "vesafb: Sorry, pre-VBE 2.0 cards are not supported.\n");
1723 + kfree(mytask);
1724 + return 1;
1725 + }
1726 +
1727 + if ((mytask->regs.eax & 0xffff) != 0x004f) {
1728 + printk(KERN_ERR "vesafb: Getting mode info block failed (eax=0x%x)\n",
1729 + (u32)mytask->regs.eax);
1730 + kfree(mytask);
1731 + return 1;
1732 + }
1733 +
1734 + printk(KERN_INFO "vesafb: %s, %s, %s (OEM: %s)\n", (char*)vbe_ib.oem_vendor_name_ptr,
1735 + (char*)vbe_ib.oem_product_name_ptr, (char*)vbe_ib.oem_product_rev_ptr,
1736 + (char*)vbe_ib.oem_string_ptr);
1737 +
1738 + printk(KERN_INFO "vesafb: VBE version: %d.%d\n",((vbe_ib.vbe_version & 0xff00) >> 8),
1739 + vbe_ib.vbe_version & 0xff);
1740 +
1741 + /* Count available modes. */
1742 + mode = (u16*)vbe_ib.mode_list_ptr;
1743 + while (*mode != 0xffff) {
1744 + vbe_modes_cnt++;
1745 + mode++;
1746 + }
1747 +
1748 + vbe_modes = kmalloc(sizeof(struct vesafb_mode_info_block)*vbe_modes_cnt,GFP_KERNEL);
1749 +
1750 + /* Get mode info for all available modes. */
1751 + mode = (u16*)vbe_ib.mode_list_ptr;
1752 +
1753 + while (*mode != 0xffff) {
1754 + mytask->regs.eax = 0x4f01;
1755 + mytask->regs.ecx = (u32) *mode;
1756 + mytask->type = VESAFB_TASK_GETVBE_MODEINFO;
1757 + mytask->res = vbe_modes+off;
1758 + mytask->done = 0;
1759 +
1760 + vesafb_queue_task (mytask);
1761 + vesafb_wait_for_task(mytask);
1762 +
1763 + vesafb_pmib(mytask->res)->mode_id = *mode;
1764 +
1765 + /* Forget text modes. */
1766 + if ((vesafb_pmib(mytask->res)->mode_attr & 0x10) != 0 &&
1767 + vesafb_pmib(mytask->res)->bits_per_pixel >= 8) {
1768 + off++;
1769 + } else {
1770 + vbe_modes_cnt--;
1771 + }
1772 + mode++;
1773 + }
1774 +
1775 + mytask->regs.eax = 0x4f0a;
1776 + mytask->regs.ebx = 0x0;
1777 + mytask->type = VESAFB_TASK_DOVM86;
1778 + mytask->res = NULL;
1779 + mytask->done = 0;
1780 +
1781 + vesafb_queue_task(mytask);
1782 + vesafb_wait_for_task(mytask);
1783 +
1784 + if ((mytask->regs.eax & 0xffff) != 0x004f || mytask->regs.es < 0xc000) {
1785 + pmi_setpal = ypan = 0;
1786 + } else {
1787 + pmi_base = (unsigned short*)phys_to_virt(((unsigned long)mytask->regs.es << 4) + mytask->regs.edi);
1788 + pmi_start = (void*)((char*)pmi_base + pmi_base[1]);
1789 + pmi_pal = (void*)((char*)pmi_base + pmi_base[2]);
1790 + printk(KERN_INFO "vesafb: protected mode interface info at %04x:%04x\n",
1791 + (u16)mytask->regs.es, (u16)mytask->regs.edi);
1792 + printk(KERN_INFO "vesafb: pmi: set display start = %p, set palette = %p\n",
1793 + pmi_start, pmi_pal);
1794 +
1795 + if (pmi_base[3]) {
1796 + printk(KERN_INFO "vesafb: pmi: ports = ");
1797 + for (i = pmi_base[3]/2; pmi_base[i] != 0xffff; i++)
1798 + printk("%x ",pmi_base[i]);
1799 + printk("\n");
1800 +
1801 + if (pmi_base[i] != 0xffff) {
1802 + /*
1803 + * memory areas not supported (yet?)
1804 + *
1805 + * Rules are: we have to set up a descriptor for the requested
1806 + * memory area and pass it in the ES register to the BIOS function.
1807 + */
1808 + printk(KERN_INFO "vesafb: can't handle memory requests, pmi disabled\n");
1809 + ypan = pmi_setpal = 0;
1810 + }
1811 + }
1812 + }
1813 +
1814 + if (noedid || vbe_ib.vbe_version < 0x0300)
1815 + goto set_monspecs;
1816 +
1817 + mytask->regs.eax = 0x4f15;
1818 + mytask->regs.ebx = 0;
1819 + mytask->regs.ecx = 0;
1820 + mytask->done = 0;
1821 +
1822 + vesafb_queue_task(mytask);
1823 + vesafb_wait_for_task(mytask);
1824 +
1825 + if ((mytask->regs.eax & 0xffff) != 0x004f)
1826 + goto set_monspecs;
1827 +
1828 + if ((mytask->regs.ebx & 0x3) == 3) {
1829 + printk(KERN_INFO "vesafb: hardware supports both DDC1 and DDC2 transfers\n");
1830 + } else if ((mytask->regs.ebx & 0x3) == 2) {
1831 + printk(KERN_INFO "vesafb: hardware supports DDC2 transfers\n");
1832 + } else if ((mytask->regs.ebx & 0x3) == 1) {
1833 + printk(KERN_INFO "vesafb: hardware supports DDC1 transfers\n");
1834 + } else {
1835 + printk(KERN_INFO "vesafb: hardware doesn't support DDC transfers\n");
1836 + goto set_monspecs;
1837 + }
1838 +
1839 + mytask->regs.eax = 0x4f15;
1840 + mytask->regs.ebx = 1;
1841 + mytask->regs.ecx = mytask->regs.edx = mytask->done = 0;
1842 + mytask->type = VESAFB_TASK_GETEDID;
1843 + mytask->res = kmalloc(EDID_LENGTH, GFP_KERNEL);
1844 +
1845 + vesafb_queue_task(mytask);
1846 + vesafb_wait_for_task(mytask);
1847 +
1848 + if ((mytask->regs.eax & 0xffff) == 0x004f) {
1849 + mon_limits = !fb_get_monitor_limits(mytask->res, &info->monspecs);
1850 +
1851 + /* If no maximum clock is specified, set to 300 MHz. */
1852 + if (mon_limits && info->monspecs.dclkmax == 0) {
1853 + info->monspecs.dclkmax = 300 * 1000000;
1854 + }
1855 +
1856 + edid_modes = fb_create_modedb(mytask->res, &edid_modes_cnt);
1857 + }
1858 + kfree(mytask->res);
1859 +
1860 +set_monspecs:
1861 + if (maxclk)
1862 + info->monspecs.dclkmax = maxclk * 1000000;
1863 +
1864 + if (maxvf)
1865 + info->monspecs.vfmax = maxvf;
1866 +
1867 + if (maxhf)
1868 + info->monspecs.hfmax = maxhf * 1000;
1869 +
1870 + /* In case DDC transfers are not supported the user can provide monitor limits
1871 + manually, lower limits are set to "safe" values. */
1872 + if (!mon_limits && maxclk && maxvf && maxhf) {
1873 + info->monspecs.dclkmin = 0;
1874 + info->monspecs.vfmin = 60;
1875 + info->monspecs.hfmin = 29000;
1876 + }
1877 +
1878 + printk(KERN_INFO "vesafb: monitor limits: vf = %d Hz, hf = %d kHz, clk = %d MHz\n",
1879 + info->monspecs.vfmax, (int)(info->monspecs.hfmax / 1000),
1880 + (int)(info->monspecs.dclkmax / 1000000));
1881 +
1882 + kfree(mytask);
1883 + return 0;
1884 +}
1885 +
1886 +static int __init decode_mode(u32 *xres, u32 *yres, u32 *bpp, u32 *refresh)
1887 +{
1888 + int len = strlen(mode_option), i, err = 0;
1889 + u8 res_specified = 0, bpp_specified = 0, refresh_specified = 0,
1890 + yres_specified = 0;
1891 +
1892 + for (i = len-1; i >= 0; i--) {
1893 + switch (mode_option[i]) {
1894 + case '@':
1895 + len = i;
1896 + if (!refresh_specified && !bpp_specified &&
1897 + !yres_specified) {
1898 + *refresh = simple_strtoul(&mode_option[i+1], NULL, 0);
1899 + refresh_specified = 1;
1900 + } else
1901 + goto out;
1902 + break;
1903 + case '-':
1904 + len = i;
1905 + if (!bpp_specified && !yres_specified) {
1906 + *bpp = simple_strtoul(&mode_option[i+1], NULL, 0);
1907 + bpp_specified = 1;
1908 + } else
1909 + goto out;
1910 + break;
1911 + case 'x':
1912 + if (!yres_specified) {
1913 + *yres = simple_strtoul(&mode_option[i+1], NULL, 0);
1914 + yres_specified = 1;
1915 + } else
1916 + goto out;
1917 + break;
1918 + case '0'...'9':
1919 + break;
1920 + default:
1921 + goto out;
1922 + }
1923 + }
1924 +
1925 + if (i < 0 && yres_specified) {
1926 + *xres = simple_strtoul(mode_option, NULL, 0);
1927 + res_specified = 1;
1928 + }
1929 +
1930 +out: if (!res_specified || !yres_specified) {
1931 + printk(KERN_ERR "vesafb: invalid resolution, %s not specified\n",
1932 + (!res_specified) ? "width" : "height");
1933 + err = -EINVAL;
1934 + }
1935 +
1936 + return err;
1937 +}
1938 +
1939 +static int __init vesafb_init_set_mode(struct fb_info *info)
1940 +{
1941 + char buf[32];
1942 + int i, modeid, refresh = 0;
1943 + u8 refresh_specified = 0;
1944 +
1945 + if (!mode_option)
1946 + mode_option = CONFIG_FB_VESA_DEFAULT_MODE;
1947 +
1948 + if (vbemode > 0) {
1949 + for (i = 0; i < vbe_modes_cnt; i++) {
1950 + if (vbe_modes[i].mode_id == vbemode) {
1951 + info->var.vmode = FB_VMODE_NONINTERLACED;
1952 + info->var.sync = FB_SYNC_VERT_HIGH_ACT;
1953 + vesafb_setup_var(&info->var, info, &vbe_modes[i]);
1954 + fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60, &info->var, info);
1955 + return i;
1956 + }
1957 + }
1958 +
1959 + printk(KERN_INFO "specified VBE mode %d not found\n",vbemode);
1960 + }
1961 +
1962 + if (decode_mode(&info->var.xres, &info->var.yres,
1963 + &info->var.bits_per_pixel, &refresh)) {
1964 + return -EINVAL;
1965 + }
1966 + if (refresh) {
1967 + refresh_specified = 1;
1968 + } else {
1969 + refresh = 60;
1970 + }
1971 + modeid = vesafb_find_vbe_mode(info->var.xres, info->var.yres, info->var.bits_per_pixel, 0);
1972 +
1973 + if (modeid == -1) {
1974 + return -EINVAL;
1975 + } else {
1976 + info->var.vmode = FB_VMODE_NONINTERLACED;
1977 + info->var.sync = FB_SYNC_VERT_HIGH_ACT;
1978 + vesafb_setup_var(&info->var, info, &vbe_modes[modeid]);
1979 + }
1980 +
1981 + if (gtf)
1982 + goto timings_gtf;
1983 +
1984 + sprintf(buf, "%dx%d-%d@%d", info->var.xres, info->var.yres, info->var.bits_per_pixel, refresh);
1985 + i = fb_find_mode(&info->var, info, buf, vesa_modes, VESA_MODEDB_SIZE, NULL, 0);
1986 + DPRINTK("fb_find_mode returned %d\n", i);
1987 +
1988 + if (i == 1 || (i == 2 && vbe_ib.vbe_version < 0x0300))
1989 + return modeid;
1990 +
1991 + /* The call to fb_find_mode could have changed our var struct, so we need
1992 + * to restore it. */
1993 + info->var.vmode = FB_VMODE_NONINTERLACED;
1994 + info->var.sync = FB_SYNC_VERT_HIGH_ACT;
1995 + vesafb_setup_var(&info->var, info, &vbe_modes[modeid]);
1996 +
1997 + if (edid_modes != NULL && !gtf) {
1998 + DPRINTK("looking for EDID modes\n");
1999 +
2000 + for (i = 0; i < edid_modes_cnt; i++) {
2001 +
2002 + if (edid_modes[i].xres == info->var.xres &&
2003 + edid_modes[i].yres == info->var.yres &&
2004 + abs(edid_modes[i].refresh - refresh) < 5) {
2005 +
2006 + info->var.pixclock = edid_modes[i].pixclock;
2007 + info->var.left_margin = edid_modes[i].left_margin;
2008 + info->var.right_margin = edid_modes[i].right_margin;
2009 + info->var.upper_margin = edid_modes[i].upper_margin;
2010 + info->var.lower_margin = edid_modes[i].lower_margin;
2011 + info->var.hsync_len = edid_modes[i].hsync_len;
2012 + info->var.vsync_len = edid_modes[i].vsync_len;
2013 + info->var.sync = edid_modes[i].sync;
2014 + info->var.vmode = edid_modes[i].vmode;
2015 + DPRINTK("using EDID-provided mode\n");
2016 + return modeid;
2017 + }
2018 + }
2019 + }
2020 +
2021 +timings_gtf:
2022 + if (refresh_specified)
2023 + i = FB_VSYNCTIMINGS;
2024 + else
2025 + i = FB_MAXTIMINGS;
2026 +
2027 + if (vbe_ib.vbe_version < 0x0300) {
2028 + i = FB_VSYNCTIMINGS | FB_IGNOREMON;
2029 + refresh = 60;
2030 + }
2031 +
2032 + if (!mon_limits)
2033 + i |= FB_IGNOREMON;
2034 +
2035 + if (!fb_get_mode(i, refresh, &info->var, info))
2036 + return modeid;
2037 +
2038 + printk(KERN_WARNING "vesafb: trying maximum allowed refresh rate\n");
2039 +
2040 + if (i & FB_VSYNCTIMINGS && refresh > 60 && mon_limits) {
2041 + if (!fb_get_mode(FB_MAXTIMINGS, refresh, &info->var, info))
2042 + return modeid;
2043 + }
2044 +
2045 + printk(KERN_WARNING "vesafb: using default BIOS refresh rate\n");
2046 + vbemode = vbe_modes[modeid].mode_id;
2047 +
2048 + return modeid;
2049 +}
2050 +
2051 +static int __init vesafb_probe(struct device *device)
2052 +{
2053 + char entry[16];
2054 + struct platform_device *dev = to_platform_device(device);
2055 + struct fb_info *info;
2056 + struct vesafb_mode_info_block *mode = NULL;
2057 + int err = 0, i, h;
2058 + unsigned int size_vmode;
2059 + unsigned int size_remap;
2060 + unsigned int size_total;
2061 +
2062 + vesafb_info = info = framebuffer_alloc(sizeof(struct vesafb_par) + sizeof(u32) * 256, &dev->dev);
2063 +
2064 + if (!info)
2065 + return -ENOMEM;
2066 +
2067 + if (vesafb_pid) {
2068 + vesafb_serv_thread = find_task_by_pid(vesafb_pid);
2069 + } else {
2070 + printk(KERN_ERR "vesafb: vesafb thread not running\n");
2071 + framebuffer_release(info);
2072 + return -EINVAL;
2073 + }
2074 +
2075 + if (vesafb_vbe_init(info)) {
2076 + printk(KERN_ERR "vesafb: vbe_init failed\n");
2077 + err = -EINVAL;
2078 + goto out;
2079 + }
2080 +
2081 + vesafb_fix.ypanstep = ypan ? 1 : 0;
2082 + vesafb_fix.ywrapstep = (ypan>1) ? 1 : 0;
2083 +
2084 + info->pseudo_palette = ((u8*)info->par + sizeof(struct vesafb_par));
2085 + info->fbops = &vesafb_ops;
2086 + info->var = vesafb_defined;
2087 + info->fix = vesafb_fix;
2088 +
2089 + if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
2090 + err = -ENXIO;
2091 + goto out;
2092 + }
2093 +
2094 + i = vesafb_init_set_mode(info);
2095 + if (i < 0)
2096 + goto out_cmap;
2097 +
2098 + /* Has the VBE mode number been specified? */
2099 + if (vbemode > 0) {
2100 + for (i = 0; i < vbe_modes_cnt; i++) {
2101 + if (vbe_modes[i].mode_id == vbemode) {
2102 + mode = &vbe_modes[i];
2103 + break;
2104 + }
2105 + }
2106 + } else {
2107 + i = vesafb_find_vbe_mode(info->var.xres, info->var.yres,
2108 + info->var.bits_per_pixel, VESAFB_NEED_EXACT_RES | VESAFB_NEED_EXACT_DEPTH);
2109 + if (i > 0)
2110 + mode = &vbe_modes[i];
2111 + }
2112 +
2113 + /* Find out how much IO memory is required for the mode with
2114 + * the highest resolution. */
2115 + size_remap = 0;
2116 + for (i = 0; i < vbe_modes_cnt; i++) {
2117 + h = vbe_modes[i].bytes_per_scan_line * vbe_modes[i].y_res;
2118 + if (h > size_remap)
2119 + size_remap = h;
2120 + }
2121 + size_remap *= 2;
2122 +
2123 + /* size_vmode -- that is the amount of memory needed for the
2124 + * used video mode, i.e. the minimum amount of
2125 + * memory we need. */
2126 + if (mode != NULL) {
2127 + size_vmode = info->var.yres * mode->bytes_per_scan_line;
2128 + } else {
2129 + size_vmode = info->var.yres * info->var.xres *
2130 + ((info->var.bits_per_pixel + 7) >> 3);
2131 + }
2132 +
2133 + /* size_total -- all video memory we have. Used for mtrr
2134 + * entries, ressource allocation and bounds
2135 + * checking. */
2136 + size_total = vbe_ib.total_memory * 65536;
2137 + if (vram_total)
2138 + size_total = vram_total * 1024 * 1024;
2139 + if (size_total < size_vmode)
2140 + size_total = size_vmode;
2141 +
2142 + /* size_remap -- the amount of video memory we are going to
2143 + * use for vesafb. With modern cards it is no
2144 + * option to simply use size_total as that
2145 + * wastes plenty of kernel address space. */
2146 + if (vram_remap)
2147 + size_remap = vram_remap * 1024 * 1024;
2148 + if (size_remap < size_vmode)
2149 + size_remap = size_vmode;
2150 + if (size_remap > size_total)
2151 + size_remap = size_total;
2152 +
2153 + info->fix.smem_len = size_remap;
2154 + info->fix.smem_start = mode->phys_base_ptr;
2155 +
2156 + /* We have to set it here, because when setup_var() was called, smem_len
2157 + wasn't defined yet. */
2158 + info->var.yres_virtual = info->fix.smem_len / mode->bytes_per_scan_line;
2159 +
2160 + if (ypan && info->var.yres_virtual > info->var.yres) {
2161 + printk(KERN_INFO "vesafb: scrolling: %s using protected mode interface, yres_virtual=%d\n",
2162 + (ypan > 1) ? "ywrap" : "ypan",info->var.yres_virtual);
2163 + } else {
2164 + printk(KERN_INFO "vesafb: scrolling: redraw\n");
2165 + info->var.yres_virtual = info->var.yres;
2166 + ypan = 0;
2167 + }
2168 +
2169 + info->flags = FBINFO_FLAG_DEFAULT |
2170 + (ypan) ? FBINFO_HWACCEL_YPAN : 0;
2171 +
2172 + if (!request_mem_region(info->fix.smem_start, size_total, "vesafb")) {
2173 + printk(KERN_WARNING "vesafb: cannot reserve video memory at 0x%lx\n", info->fix.smem_start);
2174 + /* We cannot make this fatal. Sometimes this comes from magic
2175 + spaces our resource handlers simply don't know about */
2176 + }
2177 +
2178 + info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
2179 +
2180 + if (!info->screen_base) {
2181 + printk(KERN_ERR
2182 + "vesafb: abort, cannot ioremap video memory 0x%x @ 0x%lx\n",
2183 + info->fix.smem_len, info->fix.smem_start);
2184 + err = -EIO;
2185 + goto out_mem;
2186 + }
2187 +
2188 + /* Request failure does not faze us, as vgacon probably has this
2189 + region already (FIXME) */
2190 + request_region(0x3c0, 32, "vesafb");
2191 +
2192 + if (mtrr && !(info->fix.smem_start & (PAGE_SIZE - 1))) {
2193 + int temp_size = size_total;
2194 +
2195 + /* Find the largest power-of-two */
2196 + while (temp_size & (temp_size - 1))
2197 + temp_size &= (temp_size - 1);
2198 +
2199 + /* Try and find a power of two to add */
2200 + while (temp_size && mtrr_add(info->fix.smem_start, temp_size, MTRR_TYPE_WRCOMB, 1) == -EINVAL) {
2201 + temp_size >>= 1;
2202 + }
2203 + }
2204 +
2205 + if (register_framebuffer(info) < 0) {
2206 + printk(KERN_ERR "vesafb: failed to register framebuffer device\n");
2207 + err = -EINVAL;
2208 + goto out_mem;
2209 + }
2210 +
2211 + printk(KERN_INFO "vesafb: framebuffer at 0x%lx, mapped to 0x%p, using %dk, total %dk\n",
2212 + info->fix.smem_start, info->screen_base, size_remap/1024, size_total/1024);
2213 + printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id);
2214 +
2215 + sprintf(entry, "fb%d", info->node);
2216 + proc_mkdir(entry, 0);
2217 +
2218 + sprintf(entry, "fb%d/modes", info->node);
2219 + create_proc_read_entry(entry, 0, 0, vesafb_read_proc_modes, NULL);
2220 +
2221 + sprintf(entry, "fb%d/vbe_info", info->node);
2222 + create_proc_read_entry(entry, 0, 0, vesafb_read_proc_vbe_info, NULL);
2223 +
2224 + fb_destroy_modedb(edid_modes);
2225 + return 0;
2226 +
2227 +out_mem:
2228 + release_mem_region(info->fix.smem_start, size_total);
2229 +out_cmap:
2230 + fb_dealloc_cmap(&info->cmap);
2231 +out:
2232 + framebuffer_release(info);
2233 + vesafb_info = NULL;
2234 +
2235 + fb_destroy_modedb(edid_modes);
2236 + kfree(vbe_modes);
2237 + vbe_modes = NULL;
2238 + return err;
2239 +}
2240 +
2241 +int __init vesafb_init(void)
2242 +{
2243 + int ret;
2244 +#ifndef MODULE
2245 + char *option = NULL;
2246 +
2247 + if (fb_get_options("vesafb", &option))
2248 + return -ENODEV;
2249 + vesafb_setup(option);
2250 +#endif
2251 + ret = driver_register(&vesafb_driver);
2252 +
2253 + if (!ret) {
2254 + ret = platform_device_register(&vesafb_device);
2255 + if (ret)
2256 + driver_unregister(&vesafb_driver);
2257 + }
2258 +
2259 + return ret;
2260 +}
2261 +
2262 +module_init(vesafb_init);
2263 +
2264 +#ifdef MODULE
2265 +void vesafb_exit(void)
2266 +{
2267 + char entry[16];
2268 +
2269 + if (vesafb_info)
2270 + unregister_framebuffer(vesafb_info);
2271 +
2272 + platform_device_unregister(&vesafb_device);
2273 + driver_unregister(&vesafb_driver);
2274 +
2275 + if (vesafb_info) {
2276 + sprintf(entry, "fb%d/modes", vesafb_info->node);
2277 + remove_proc_entry(entry, NULL);
2278 +
2279 + sprintf(entry, "fb%d/vbe_info", vesafb_info->node);
2280 + remove_proc_entry(entry, NULL);
2281 +
2282 + sprintf(entry, "fb%d", vesafb_info->node);
2283 + remove_proc_entry(entry, NULL);
2284 +
2285 + iounmap(info->screen_base);
2286 + release_mem_region(vesafb_info->fix.smem_start, vesafb_info->fix.smem_len);
2287 + fb_dealloc_cmap(&vesafb_info->cmap);
2288 + framebuffer_release(vesafb_info);
2289 + }
2290 +
2291 + if (vbe_modes != NULL)
2292 + kfree(vbe_modes);
2293 +}
2294 +
2295 +module_exit(vesafb_exit);
2296 +
2297 +static inline int param_get_scroll(char *buffer, struct kernel_param *kp) { return 0; }
2298 +static inline int param_set_scroll(const char *val, struct kernel_param *kp)
2299 +{
2300 + ypan = 0;
2301 +
2302 + if (! strcmp(val, "redraw"))
2303 + ypan=0;
2304 + else if (! strcmp(val, "ypan"))
2305 + ypan=1;
2306 + else if (! strcmp(val, "ywrap"))
2307 + ypan=2;
2308 +
2309 + return 0;
2310 +}
2311 +
2312 +#define param_check_scroll(name, p) __param_check(name, p, void);
2313 +
2314 +module_param_named(scroll, ypan, scroll, 0);
2315 +MODULE_PARM_DESC(scroll,"Scrolling mode, set to 'redraw', 'ypan' or 'ywrap'");
2316 +module_param_named(vgapal, pmi_setpal, invbool, 0);
2317 +MODULE_PARM_DESC(vgapal,"bool: set palette using VGA registers");
2318 +module_param_named(pmipal, pmi_setpal, bool, 0);
2319 +MODULE_PARM_DESC(pmipal,"bool: set palette using PMI calls");
2320 +module_param_named(nomtrr, mtrr, invbool, 0);
2321 +MODULE_PARM_DESC(nomtrr,"bool: disable use of MTRR registers");
2322 +module_param(nocrtc, bool, 0);
2323 +MODULE_PARM_DESC(nocrtc,"bool: ignore CRTC timings when setting modes");
2324 +module_param(noedid, bool, 0);
2325 +MODULE_PARM_DESC(noedid,"bool: ignore EDID-provided monitor limits when setting modes");
2326 +module_param(gtf, bool, 0);
2327 +MODULE_PARM_DESC(gtf,"bool: force use of VESA GTF to calculate mode timings");
2328 +module_param(vram_remap, uint, 0);
2329 +MODULE_PARM_DESC(vram_remap,"Set amount of video memory to be used [MiB]");
2330 +module_param(vram_total, uint, 0);
2331 +MODULE_PARM_DESC(vram_total,"Set total amount of video memoery [MiB]");
2332 +module_param(maxclk, ushort, 0);
2333 +MODULE_PARM_DESC(maxclk,"Maximum pixelclock [MHz], overrides EDID data");
2334 +module_param(maxhf, ushort, 0);
2335 +MODULE_PARM_DESC(maxhf,"Maximum horizontal frequency [kHz], overrides EDID data");
2336 +module_param(maxvf, ushort, 0);
2337 +MODULE_PARM_DESC(maxvf,"Maximum vertical frequency [Hz], overrides EDID data");
2338 +module_param_named(mode, mode_option, charp, 0);
2339 +MODULE_PARM_DESC(mode,"Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\"");
2340 +module_param(vbemode, ushort, 0);
2341 +MODULE_PARM_DESC(vbemode,"VBE mode number to set, overrides 'mode' setting");
2342 +
2343 +#endif /* MODULE */
2344 +
2345 +MODULE_LICENSE("GPL");
2346 +MODULE_AUTHOR("Michal Januszewski");
2347 +MODULE_DESCRIPTION("Framebuffer driver for VBE2.0+ compliant graphic boards");
2348 +
2349 diff --git a/include/video/vesa.h b/include/video/vesa.h
2350 new file mode 100644
2351 --- /dev/null
2352 +++ b/include/video/vesa.h
2353 @@ -0,0 +1,122 @@
2354 +#define crtc_pib(arg) ((struct vesafb_crtc_info_block*)(arg))
2355 +#define vbe_pib(arg) ((struct vesafb_vbe_info_block*)(arg))
2356 +#define vesafb_pmib(arg) ((struct vesafb_mode_info_block*)(arg))
2357 +
2358 +struct vesafb_task {
2359 + enum {
2360 + VESAFB_TASK_DOVM86,
2361 + VESAFB_TASK_GETVBE_IB,
2362 + VESAFB_TASK_GETVBE_MODEINFO,
2363 + VESAFB_TASK_SWITCHMODE,
2364 + VESAFB_TASK_GETEDID,
2365 + VESAFB_TASK_SETPAL
2366 + } type;
2367 +
2368 + unsigned short flags;
2369 + struct vm86_regs regs;
2370 +
2371 + unsigned char done;
2372 + void *res;
2373 +
2374 + struct list_head node;
2375 +};
2376 +
2377 +#define VESAFB_FLAG_FREESTRUCT 0x0001
2378 +#define VESAFB_CAP_CAN_SWITCH_DAC 0x01
2379 +
2380 +/* this struct is 512 bytes long */
2381 +struct vesafb_vbe_info_block {
2382 + char vbe_signature[4];
2383 + u16 vbe_version;
2384 + u32 oem_string_ptr;
2385 + u32 capabilities;
2386 + u32 mode_list_ptr;
2387 + u16 total_memory;
2388 + u16 oem_software_rev;
2389 + u32 oem_vendor_name_ptr;
2390 + u32 oem_product_name_ptr;
2391 + u32 oem_product_rev_ptr;
2392 + u8 reserved[222];
2393 + char oem_data[256];
2394 +} __attribute__ ((packed));
2395 +
2396 +struct vesafb_crtc_info_block {
2397 + u16 horiz_total;
2398 + u16 horiz_start;
2399 + u16 horiz_end;
2400 + u16 vert_total;
2401 + u16 vert_start;
2402 + u16 vert_end;
2403 + u8 flags;
2404 + u32 pixel_clock;
2405 + u16 refresh_rate;
2406 + u8 reserved[40];
2407 +} __attribute__ ((packed));
2408 +
2409 +/* this struct is 256 bytes long */
2410 +struct vesafb_mode_info_block {
2411 +
2412 + /* for all VBE revisions */
2413 + u16 mode_attr;
2414 + u8 winA_attr;
2415 + u8 winB_attr;
2416 + u16 win_granularity;
2417 + u16 win_size;
2418 + u16 winA_seg;
2419 + u16 winB_seg;
2420 + u32 win_func_ptr;
2421 + u16 bytes_per_scan_line;
2422 +
2423 + /* for VBE 1.2+ */
2424 + u16 x_res;
2425 + u16 y_res;
2426 + u8 x_char_size;
2427 + u8 y_char_size;
2428 + u8 planes;
2429 + u8 bits_per_pixel;
2430 + u8 banks;
2431 + u8 memory_model;
2432 + u8 bank_size;
2433 + u8 image_pages;
2434 + u8 reserved1;
2435 +
2436 + /* direct color fields for direct/6 and YUV/7 memory models */
2437 + u8 red_len;
2438 + u8 red_off; /* offsets are bit positions of lsb in the mask */
2439 + u8 green_len;
2440 + u8 green_off;
2441 + u8 blue_len;
2442 + u8 blue_off;
2443 + u8 rsvd_len;
2444 + u8 rsvd_off;
2445 + u8 direct_color_info; /* direct color mode attributes */
2446 +
2447 + /* for VBE 2.0+ */
2448 + u32 phys_base_ptr;
2449 + u8 reserved2[6];
2450 +
2451 + /* for VBE 3.0+ */
2452 + u16 lin_bytes_per_scan_line;
2453 + u8 bnk_image_pages;
2454 + u8 lin_image_pages;
2455 + u8 lin_red_len;
2456 + u8 lin_red_off;
2457 + u8 lin_green_len;
2458 + u8 lin_green_off;
2459 + u8 lin_blue_len;
2460 + u8 lin_blue_off;
2461 + u8 lin_rsvd_len;
2462 + u8 lin_rsvd_off;
2463 + u32 max_pixel_clock;
2464 + u16 mode_id;
2465 +} __attribute__ ((packed));
2466 +
2467 +struct vesafb_par {
2468 + u16 vbe_mode;
2469 + struct vesafb_crtc_info_block crtc;
2470 +};
2471 +
2472 +struct vesafb_pal_entry {
2473 + u_char blue, green, red, pad;
2474 +} __attribute__ ((packed));
2475 +

  ViewVC Help
Powered by ViewVC 1.1.20