/[linux-patches]/genpatches-2.6/trunk/2.6.12-pre/4505_vesafb-tng-0.9-rc6.patch
Gentoo

Contents of /genpatches-2.6/trunk/2.6.12-pre/4505_vesafb-tng-0.9-rc6.patch

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.20