/[linux-patches]/genpatches-2.6/tags/2.6.12-12/4505_vesafb-tng-0.9-rc6-r2.patch
Gentoo

Contents of /genpatches-2.6/tags/2.6.12-12/4505_vesafb-tng-0.9-rc6-r2.patch

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.20