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

Contents of /genpatches-2.6/tags/2.6.13-4/4505_vesafb-tng-0.9-rc7-r1.patch

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.20