/[linux-patches]/genpatches-2.6/tags/2.6.20-9/4205_vesafb-tng-1.0-rc2.patch
Gentoo

Contents of /genpatches-2.6/tags/2.6.20-9/4205_vesafb-tng-1.0-rc2.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 927 - (show annotations) (download)
Thu Apr 26 15:33:43 2007 UTC (7 years, 4 months ago) by phreak
File size: 91340 byte(s)
2.6.20-9 release
1 Index: linux-git/Documentation/fb/vesafb.txt
2 ===================================================================
3 --- linux-git.orig/Documentation/fb/vesafb.txt
4 +++ linux-git/Documentation/fb/vesafb.txt
5 @@ -2,16 +2,18 @@
6 What is vesafb?
7 ===============
8
9 -This is a generic driver for a graphic framebuffer on intel boxes.
10 +Vesafb is a generic framebuffer driver for x86 and x86_64 boxes.
11
12 -The idea is simple: Turn on graphics mode at boot time with the help
13 -of the BIOS, and use this as framebuffer device /dev/fb0, like the m68k
14 -(and other) ports do.
15 -
16 -This means we decide at boot time whenever we want to run in text or
17 -graphics mode. Switching mode later on (in protected mode) is
18 -impossible; BIOS calls work in real mode only. VESA BIOS Extensions
19 -Version 2.0 are required, because we need a linear frame buffer.
20 +VESA BIOS Extensions Version 2.0 are required, because we need access to
21 +a linear frame buffer. VBE 3.0 is required if you want to use modes with a
22 +higher (than the standard 60 Hz) refresh rate.
23 +
24 +The VESA framebuffer driver comes in two flavors - the standard 'vesafb'
25 +and 'vesafb-tng'. Vesafb-tng is available only on 32-bit x86 due to the
26 +technology it uses (vm86). Vesafb-tng has more features than vesafb
27 +(adjusting the refresh rate on VBE 3.0 compliant boards, switching the
28 +video mode without rebooting, selecting a mode by providing its
29 +modedb name, and more).
30
31 Advantages:
32
33 @@ -29,26 +31,35 @@ Disadvantages:
34 How to use it?
35 ==============
36
37 -Switching modes is done using the vga=... boot parameter. Read
38 -Documentation/svga.txt for details.
39 -
40 -You should compile in both vgacon (for text mode) and vesafb (for
41 -graphics mode). Which of them takes over the console depends on
42 -whenever the specified mode is text or graphics.
43 -
44 -The graphic modes are NOT in the list which you get if you boot with
45 -vga=ask and hit return. The mode you wish to use is derived from the
46 -VESA mode number. Here are those VESA mode numbers:
47 +If you are running a 32-bit x86 system and you decide to use vesafb-tng,
48 +you can either compile the driver into the kernel or use it as a module.
49 +The graphics mode you want to use is in both cases specified using the
50 +standard modedb format.
51 +
52 +If your system doesn't support vm86 calls, things get a little more tricky.
53 +Since on such systems you can't do BIOS calls from protected mode in which
54 +kernel runs, you have to decide at boot time whenever you want to run in text
55 +or in graphics mode. Switching mode later on is impossible. Switching modes
56 +is done using the vga=... boot parameter. Read Documentation/svga.txt for
57 +details. Below is a more detailed description of what to do on systems using
58 +the standard vesafb driver.
59 +
60 +You should compile in both vgacon (for text mode) and vesafb (for graphics
61 +mode). Which of them takes over the console depends on whenever the
62 +specified mode is text or graphics.
63 +
64 +The graphic modes are NOT in the list which you get if you boot with vga=ask
65 +and hit return. The mode you wish to use is derived from the VESA mode number.
66 +Here are those VESA mode numbers:
67
68 | 640x480 800x600 1024x768 1280x1024
69 ----+-------------------------------------
70 -256 | 0x101 0x103 0x105 0x107
71 -32k | 0x110 0x113 0x116 0x119
72 -64k | 0x111 0x114 0x117 0x11A
73 -16M | 0x112 0x115 0x118 0x11B
74 +256 | 0x101 0x103 0x105 0x107
75 +32k | 0x110 0x113 0x116 0x119
76 +64k | 0x111 0x114 0x117 0x11A
77 +16M | 0x112 0x115 0x118 0x11B
78
79 -The video mode number of the Linux kernel is the VESA mode number plus
80 -0x200.
81 +The video mode number of the Linux kernel is the VESA mode number plus 0x200.
82
83 Linux_kernel_mode_number = VESA_mode_number + 0x200
84
85 @@ -56,15 +67,15 @@ So the table for the Kernel mode numbers
86
87 | 640x480 800x600 1024x768 1280x1024
88 ----+-------------------------------------
89 -256 | 0x301 0x303 0x305 0x307
90 -32k | 0x310 0x313 0x316 0x319
91 -64k | 0x311 0x314 0x317 0x31A
92 -16M | 0x312 0x315 0x318 0x31B
93 -
94 -To enable one of those modes you have to specify "vga=ask" in the
95 -lilo.conf file and rerun LILO. Then you can type in the desired
96 -mode at the "vga=ask" prompt. For example if you like to use
97 -1024x768x256 colors you have to say "305" at this prompt.
98 +256 | 0x301 0x303 0x305 0x307
99 +32k | 0x310 0x313 0x316 0x319
100 +64k | 0x311 0x314 0x317 0x31A
101 +16M | 0x312 0x315 0x318 0x31B
102 +
103 +To enable one of those modes you have to specify "vga=ask" in the lilo.conf
104 +file and rerun LILO. Then you can type in the desired mode at the "vga=ask"
105 +prompt. For example if you like to use 1024x768x256 colors you have to say
106 +"305" at this prompt.
107
108 If this does not work, this might be because your BIOS does not support
109 linear framebuffers or because it does not support this mode at all.
110 @@ -72,11 +83,12 @@ Even if your board does, it might be the
111 Extensions v2.0 are required, 1.2 is NOT sufficient. You will get a
112 "bad mode number" message if something goes wrong.
113
114 -1. Note: LILO cannot handle hex, for booting directly with
115 +1. Note: LILO cannot handle hex, for booting directly with
116 "vga=mode-number" you have to transform the numbers to decimal.
117 2. Note: Some newer versions of LILO appear to work with those hex values,
118 if you set the 0x in front of the numbers.
119
120 +
121 X11
122 ===
123
124 @@ -84,98 +96,164 @@ XF68_FBDev should work just fine, but it
125 another (accelerated) X-Server like XF86_SVGA might or might not work.
126 It depends on X-Server and graphics board.
127
128 -The X-Server must restore the video mode correctly, else you end up
129 +The X-Server must restore the video mode correctly, or else you end up
130 with a broken console (and vesafb cannot do anything about this).
131 +With vesafb-tng chances are that the console will be restored properly
132 +even if the X server messes up the video mode.
133
134
135 Refresh rates
136 =============
137
138 -There is no way to change the vesafb video mode and/or timings after
139 -booting linux. If you are not happy with the 60 Hz refresh rate, you
140 -have these options:
141 -
142 - * configure and load the DOS-Tools for your the graphics board (if
143 - available) and boot linux with loadlin.
144 - * use a native driver (matroxfb/atyfb) instead if vesafb. If none
145 +With VBE 3.0 compatible BIOSes and vesafb-tng it is possible to change
146 +the refresh rate either at boot time (by specifying the @<rr> part of
147 +the mode name) or later, using the fbset utility.
148 +
149 +If you want to use the default BIOS refresh rate while switching modes
150 +on a running system, set pixclock to 0.
151 +
152 +With VBE 2.0 there is no way to change the mode timings after booting
153 +Linux. If you are not happy with the 60 Hz refresh rate, you have
154 +the following options:
155 +
156 + * Configure and load the DOS tools for your the graphics board (if
157 + available) and boot Linux with loadlin.
158 + * Use a native driver (matroxfb/atyfb) instead of vesafb. If none
159 is available, write a new one!
160 - * VBE 3.0 might work too. I have neither a gfx board with VBE 3.0
161 - support nor the specs, so I have not checked this yet.
162 + * Use a BIOS editor to change the default refresh rate (such an
163 + editor does exist at least for ATI Radeon BIOSes).
164 + * If you're running a non-vm86 and VBE 3.0 compatible system, you can
165 + use a kernel patch (vesafb-rrc) to hard-code some mode timings in
166 + the kernel and use these while setting the video mode at boot time.
167 +
168 +Note that there are some boards (nVidia 59**, 57** and newer models)
169 +claiming that their Video BIOS is VBE 3.0 compliant, while ignoring the
170 +CRTC values provided by software such as vesafb-tng. You'll not be able
171 +to adjust the refresh rate if you're using one of these boards.
172
173
174 Configuration
175 =============
176
177 -The VESA BIOS provides protected mode interface for changing
178 -some parameters. vesafb can use it for palette changes and
179 -to pan the display. It is turned off by default because it
180 -seems not to work with some BIOS versions, but there are options
181 -to turn it on.
182 -
183 -You can pass options to vesafb using "video=vesafb:option" on
184 -the kernel command line. Multiple options should be separated
185 -by comma, like this: "video=vesafb:ypan,invers"
186 -
187 -Accepted options:
188 -
189 -invers no comment...
190 -
191 -ypan enable display panning using the VESA protected mode
192 - interface. The visible screen is just a window of the
193 - video memory, console scrolling is done by changing the
194 - start of the window.
195 - pro: * scrolling (fullscreen) is fast, because there is
196 - no need to copy around data.
197 - * You'll get scrollback (the Shift-PgUp thing),
198 - the video memory can be used as scrollback buffer
199 - kontra: * scrolling only parts of the screen causes some
200 - ugly flicker effects (boot logo flickers for
201 - example).
202 -
203 -ywrap Same as ypan, but assumes your gfx board can wrap-around
204 - the video memory (i.e. starts reading from top if it
205 - reaches the end of video memory). Faster than ypan.
206 -
207 -redraw scroll by redrawing the affected part of the screen, this
208 - is the safe (and slow) default.
209 -
210 -
211 -vgapal Use the standard vga registers for palette changes.
212 - This is the default.
213 -pmipal Use the protected mode interface for palette changes.
214 -
215 -mtrr:n setup memory type range registers for the vesafb framebuffer
216 - where n:
217 - 0 - disabled (equivalent to nomtrr) (default)
218 - 1 - uncachable
219 - 2 - write-back
220 - 3 - write-combining
221 - 4 - write-through
222 +The VESA BIOS provides protected mode interface for changing some parameters.
223 +vesafb can use it for palette changes and to pan the display. It is turned
224 +off by default because it seems not to work with some BIOS versions, but
225 +there are options to turn it on.
226 +
227 +You can pass options to vesafb using "video=vesafb:option" on the kernel
228 +command line. Multiple options should be separated by a comma, like this:
229 +"video=vesafb:ypan,1024x768-32@85"
230 +
231 +Note that vesafb-tng still uses the "video=vesafb:option" format of the
232 +kernel command line video parameter. "video=vesafb-tng:xxx" is incorrect.
233 +
234 +Accepted options (both vesafb and vesafb-tng):
235 +
236 +ypan Enable display panning using the VESA protected mode interface
237 + The visible screen is just a window of the video memory,
238 + console scrolling is done by changing the start of the window.
239 + pro: * scrolling (fullscreen) is fast, because there is
240 + no need to copy around data.
241 + * you'll get scrollback (the Shift-PgUp thing),
242 + the video memory can be used as scrollback buffer
243 + con: * scrolling only parts of the screen causes some
244 + ugly flicker effects (boot logo flickers for
245 + example).
246 +
247 +ywrap Same as ypan, but assumes your gfx board can wrap-around the video
248 + memory (i.e. starts reading from top if it reaches the end of
249 + video memory). Faster than ypan.
250 +
251 +redraw Scroll by redrawing the affected part of the screen, this is the
252 + safe (and slow) default.
253 +
254 +vgapal Use the standard VGA registers for palette changes.
255 +
256 +pmipal Use the protected mode interface for palette changes.
257 + This is the default is the protected mode interface is available.
258 +
259 +mtrr:n Setup memory type range registers for the vesafb framebuffer
260 + where n:
261 + 0 - disabled (equivalent to nomtrr) (default)
262 + 1 - uncachable
263 + 2 - write-back
264 + 3 - write-combining
265 + 4 - write-through
266
267 - If you see the following in dmesg, choose the type that matches the
268 - old one. In this example, use "mtrr:2".
269 + If you see the following in dmesg, choose the type that matches
270 + the old one. In this example, use "mtrr:2".
271 ...
272 mtrr: type mismatch for e0000000,8000000 old: write-back new: write-combining
273 ...
274
275 -nomtrr disable mtrr
276 +nomtrr Do not use memory type range registers for vesafb.
277
278 vremap:n
279 remap 'n' MiB of video RAM. If 0 or not specified, remap memory
280 - according to video mode. (2.5.66 patch/idea by Antonino Daplas
281 - reversed to give override possibility (allocate more fb memory
282 - than the kernel would) to 2.4 by tmb@iki.fi)
283 + according to video mode. (2.5.66 patch/idea by Antonino Daplas
284 + reversed to give override possibility (allocate more fb memory
285 + than the kernel would) to 2.4 by tmb@iki.fi)
286
287 vtotal:n
288 if the video BIOS of your card incorrectly determines the total
289 amount of video RAM, use this option to override the BIOS (in MiB).
290
291 -Have fun!
292 +Options accepted only by vesafb-tng:
293
294 - Gerd
295 +<mode> The mode you want to set, in the standard modedb format. Refer to
296 + modedb.txt for a detailed description. If you specify a mode that is
297 + not supported by your board's BIOS, vesafb-tng will attempt to set a
298 + similar mode. The list of supported modes can be found in
299 + /proc/fbx/modes, where x is the framebuffer number (usually 0).
300 + When vesafb-tng is compiled as a module, the mode string should be
301 + provided as a value of the parameter 'mode'.
302 +
303 +vbemode:x
304 + Force the use of VBE mode x. The mode will only be set if it's
305 + found in the VBE-provided list of supported modes.
306 + NOTE: The mode number 'x' should be specified in VESA mode number
307 + notation, not the Linux kernel one (eg. 257 instead of 769).
308 + HINT: If you use this option because normal <mode> parameter does
309 + not work for you and you use a X server, you'll probably want to
310 + set the 'nocrtc' option to ensure that the video mode is properly
311 + restored after console <-> X switches.
312 +
313 +nocrtc Do not use CRTC timings while setting the video mode. This option
314 + makes sence only with VBE 3.0 compliant systems. Use it if you have
315 + problems with modes set in the standard way. Note that using this
316 + option means that any refresh rate adjustments will be ignored
317 + and the refresh rate will stay at your BIOS default (60 Hz).
318 +
319 +noedid Do not try to fetch and use EDID-provided modes.
320 +
321 +noblank Disable hardware blanking.
322 +
323 +gtf Force the use of VESA's GTF (Generalized Timing Formula). Specifying
324 + this will cause vesafb to skip its internal modedb and EDID-modedb
325 + and jump straight to the GTF part of the code (normally used only if
326 + everything else failed). This can be useful if you want to get as
327 + much as possible from your graphics board but your BIOS doesn't
328 + support modes with the refresh rates you require. Note that you may
329 + need to specify the maxhf, maxvf and maxclk parameters if they are not
330 + provided by the EDID block.
331 +
332 +Additionally, the following parameters may be provided. They all override the
333 +EDID-provided values and BIOS defaults. Refer to your monitor's specs to get
334 +the correct values for maxhf, maxvf and maxclk for your hardware.
335 +
336 +maxhf:n Maximum horizontal frequency (in kHz).
337 +maxvf:n Maximum vertical frequency (in Hz).
338 +maxclk:n Maximum pixel clock (in MHz).
339 +
340 +Have fun!
341
342 --
343 +Original document for the vesafb driver by
344 Gerd Knorr <kraxel@goldbach.in-berlin.de>
345
346 -Minor (mostly typo) changes
347 -by Nico Schmoigl <schmoigl@rumms.uni-mannheim.de>
348 +Minor (mostly typo) changes by
349 +Nico Schmoigl <schmoigl@rumms.uni-mannheim.de>
350 +
351 +Extended documentation for vm86, VBE 3.0 and vesafb-tng by
352 +Michal Januszewski <spock@gentoo.org>
353 +
354 Index: linux-git/arch/i386/boot/video.S
355 ===================================================================
356 --- linux-git.orig/arch/i386/boot/video.S
357 +++ linux-git/arch/i386/boot/video.S
358 @@ -163,10 +163,12 @@ basret: ret
359 # parameters in the default 80x25 mode -- these are set directly,
360 # because some very obscure BIOSes supply insane values.
361 mode_params:
362 +#ifdef CONFIG_FB_VESA_STD
363 #ifdef CONFIG_VIDEO_SELECT
364 cmpb $0, graphic_mode
365 jnz mopar_gr
366 #endif
367 +#endif
368 movb $0x03, %ah # Read cursor position
369 xorb %bh, %bh
370 int $0x10
371 @@ -199,6 +201,7 @@ mopar2: movb %al, %fs:(PARAM_VIDEO_LINES
372 ret
373
374 #ifdef CONFIG_VIDEO_SELECT
375 +#ifdef CONFIG_FB_VESA_STD
376 # Fetching of VESA frame buffer parameters
377 mopar_gr:
378 leaw modelist+1024, %di
379 @@ -281,6 +284,7 @@ dac_done:
380 movw %es, %fs:(PARAM_VESAPM_SEG)
381 movw %di, %fs:(PARAM_VESAPM_OFF)
382 no_pm: ret
383 +#endif
384
385 # The video mode menu
386 mode_menu:
387 @@ -495,10 +499,12 @@ mode_set:
388
389 cmpb $VIDEO_FIRST_V7>>8, %ah
390 jz setv7
391 -
392 +
393 +#ifdef CONFIG_FB_VESA_STD
394 cmpb $VIDEO_FIRST_VESA>>8, %ah
395 jnc check_vesa
396 -
397 +#endif
398 +
399 orb %ah, %ah
400 jz setmenu
401
402 @@ -570,6 +576,7 @@ setr1: lodsw
403 movw -4(%si), %ax # Fetch mode ID
404 jmp _m_s
405
406 +#ifdef CONFIG_FB_VESA_STD
407 check_vesa:
408 leaw modelist+1024, %di
409 subb $VIDEO_FIRST_VESA>>8, %bh
410 @@ -603,6 +610,7 @@ check_vesa:
411 ret
412
413 _setbad: jmp setbad # Ugly...
414 +#endif
415
416 # Recalculate vertical display end registers -- this fixes various
417 # inconsistencies of extended modes on many adapters. Called when
418 Index: linux-git/drivers/char/sysrq.c
419 ===================================================================
420 --- linux-git.orig/drivers/char/sysrq.c
421 +++ linux-git/drivers/char/sysrq.c
422 @@ -240,7 +240,7 @@ static void send_sig_all(int sig)
423 struct task_struct *p;
424
425 for_each_process(p) {
426 - if (p->mm && !is_init(p))
427 + if (p->mm && !is_init(p) && !(p->flags & PF_BORROWED_MM))
428 /* Not swapper, init nor kernel thread */
429 force_sig(sig, p);
430 }
431 Index: linux-git/drivers/video/Kconfig
432 ===================================================================
433 --- linux-git.orig/drivers/video/Kconfig
434 +++ linux-git/drivers/video/Kconfig
435 @@ -547,8 +547,22 @@ config FB_TGA
436 cards. Say Y if you have one of those.
437
438 config FB_VESA
439 - bool "VESA VGA graphics support"
440 - depends on (FB = y) && X86
441 + tristate "VESA VGA graphics support"
442 + depends on (FB = y) && (X86 || X86_64)
443 + help
444 + This is the frame buffer device driver for generic VESA 2.0
445 + compliant graphic cards. The older VESA 1.2 cards are not supported.
446 + You will get a boot time penguin logo at no additional cost. Please
447 + read <file:Documentation/fb/vesafb.txt>. If unsure, say Y.
448 +
449 +choice
450 + prompt "VESA driver type"
451 + depends on FB_VESA
452 + default FB_VESA_STD if X86_64
453 + default FB_VESA_TNG if X86
454 +
455 +config FB_VESA_STD
456 + bool "vesafb"
457 select FB_CFB_FILLRECT
458 select FB_CFB_COPYAREA
459 select FB_CFB_IMAGEBLIT
460 @@ -557,7 +571,43 @@ config FB_VESA
461 This is the frame buffer device driver for generic VESA 2.0
462 compliant graphic cards. The older VESA 1.2 cards are not supported.
463 You will get a boot time penguin logo at no additional cost. Please
464 - read <file:Documentation/fb/vesafb.txt>. If unsure, say Y.
465 + read <file:Documentation/fb/vesafb.txt>. Choose this driver if you
466 + are experiencing problems with vesafb-tng or if you own a 64-bit system.
467 +
468 + Note that this driver cannot be compiled as a module.
469 +
470 +config FB_VESA_TNG
471 + bool "vesafb-tng"
472 + depends on !X86_64
473 + select FB_MODE_HELPERS
474 + select FB_CFB_FILLRECT
475 + select FB_CFB_COPYAREA
476 + select FB_CFB_IMAGEBLIT
477 + help
478 + This is an enhanced generic frame buffer device driver for
479 + VBE 2.0 compliant graphic cards. It can take advantage of VBE 3.0
480 + features (refresh rate adjustment) when these are available.
481 + The driver also makes it possible to change the video mode
482 + on the fly and to switch back to text mode when it's unloaded.
483 +
484 + If the driver is compiled as a module, the module will be called
485 + vesafb-tng.
486 +
487 +endchoice
488 +
489 +config FB_VESA_DEFAULT_MODE
490 + string "VESA default mode"
491 + depends on FB_VESA_TNG
492 + default "640x480@60"
493 + help
494 + This option is used to determine the default mode vesafb is
495 + supposed to switch to in case no mode is provided as a kernel
496 + command line parameter.
497 +
498 +config VIDEO_SELECT
499 + bool
500 + depends on FB_VESA
501 + default y
502
503 config FB_IMAC
504 bool "Intel-based Macintosh Framebuffer Support"
505 Index: linux-git/drivers/video/Makefile
506 ===================================================================
507 --- linux-git.orig/drivers/video/Makefile
508 +++ linux-git/drivers/video/Makefile
509 @@ -103,7 +103,11 @@ obj-$(CONFIG_FB_PNX4008_DUM_RGB) += pnx
510 obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o
511
512 # Platform or fallback drivers go here
513 -obj-$(CONFIG_FB_VESA) += vesafb.o
514 +ifeq ($(CONFIG_FB_VESA_STD),y)
515 + obj-y += vesafb.o
516 +else
517 + obj-$(CONFIG_FB_VESA) += vesafb-thread.o vesafb-tng.o
518 +endif
519 obj-$(CONFIG_FB_IMAC) += imacfb.o
520 obj-$(CONFIG_FB_VGA16) += vga16fb.o vgastate.o
521 obj-$(CONFIG_FB_OF) += offb.o
522 Index: linux-git/drivers/video/fbmem.c
523 ===================================================================
524 --- linux-git.orig/drivers/video/fbmem.c
525 +++ linux-git/drivers/video/fbmem.c
526 @@ -1408,6 +1408,7 @@ fbmem_init(void)
527 printk(KERN_WARNING "Unable to create fb class; errno = %ld\n", PTR_ERR(fb_class));
528 fb_class = NULL;
529 }
530 +
531 return 0;
532 }
533
534 Index: linux-git/drivers/video/modedb.c
535 ===================================================================
536 --- linux-git.orig/drivers/video/modedb.c
537 +++ linux-git/drivers/video/modedb.c
538 @@ -674,6 +674,7 @@ void fb_var_to_videomode(struct fb_video
539 {
540 u32 pixclock, hfreq, htotal, vtotal;
541
542 + mode->refresh = 0;
543 mode->name = NULL;
544 mode->xres = var->xres;
545 mode->yres = var->yres;
546 @@ -1025,3 +1026,4 @@ EXPORT_SYMBOL(fb_find_best_mode);
547 EXPORT_SYMBOL(fb_find_nearest_mode);
548 EXPORT_SYMBOL(fb_videomode_to_modelist);
549 EXPORT_SYMBOL(fb_find_mode);
550 +EXPORT_SYMBOL(fb_destroy_modelist);
551 Index: linux-git/drivers/video/vesafb-thread.c
552 ===================================================================
553 --- /dev/null
554 +++ linux-git/drivers/video/vesafb-thread.c
555 @@ -0,0 +1,751 @@
556 +/*
557 + * Framebuffer driver for VBE 2.0+ compliant graphic boards.
558 + * Kernel thread and vm86 routines.
559 + *
560 + * (c) 2004-2006 Michal Januszewski <spock@gentoo.org>
561 + *
562 + */
563 +
564 +#include <linux/workqueue.h>
565 +#include <linux/completion.h>
566 +#include <linux/module.h>
567 +#include <linux/kernel.h>
568 +#include <linux/errno.h>
569 +#include <linux/mm.h>
570 +#include <linux/delay.h>
571 +#include <linux/signal.h>
572 +#include <linux/freezer.h>
573 +#include <linux/suspend.h>
574 +#include <linux/unistd.h>
575 +#include <video/vesa.h>
576 +#include <video/edid.h>
577 +#include <asm/mman.h>
578 +#include <asm/page.h>
579 +#include <asm/vm86.h>
580 +#include <asm/thread_info.h>
581 +#include <asm/uaccess.h>
582 +#include <asm/mmu_context.h>
583 +#include "edid.h"
584 +
585 +static int errno;
586 +
587 +static DECLARE_COMPLETION(vesafb_th_completion);
588 +static DECLARE_MUTEX(vesafb_task_list_sem);
589 +static LIST_HEAD(vesafb_task_list);
590 +static DECLARE_WAIT_QUEUE_HEAD(vesafb_wait);
591 +
592 +static struct vm86_struct vm86;
593 +static int vesafb_pid = 0;
594 +
595 +#define DEFAULT_VM86_FLAGS (IF_MASK | IOPL_MASK)
596 +#define VM86_PUSHW(x) \
597 +do { \
598 + vm86.regs.esp -= 2; \
599 + *(u16*)(STACK_ADDR + vm86.regs.esp) = x; \
600 +} while(0);
601 +
602 +/* Stack, the return code and buffers will be put into
603 + * one contiguous memory chunk:
604 + *
605 + * [ STACK | RET_CODE | BUFFER ]
606 + *
607 + * Some video BIOSes (sis6326) try to store data somewhere
608 + * in 0x7000-0x7fff, so we zeromap more memory to be safe.
609 + */
610 +#define IVTBDA_SIZE PAGE_SIZE
611 +#define RET_CODE_SIZE 0x0010
612 +#define STACK_SIZE 0x0500
613 +#define BUFFER_SIZE 0x10000
614 +
615 +/* The amount of memory that will be allocated should be a multiple
616 + * of PAGE_SIZE. */
617 +#define __MEM_SIZE (RET_CODE_SIZE + STACK_SIZE + BUFFER_SIZE)
618 +#define REAL_MEM_SIZE (((__MEM_SIZE / PAGE_SIZE) + 1) * PAGE_SIZE)
619 +
620 +#define IVTBDA_ADDR 0x00000
621 +#define STACK_ADDR (IVTBDA_ADDR + IVTBDA_SIZE)
622 +#define RET_CODE_ADDR (STACK_ADDR + STACK_SIZE)
623 +#define BUF_ADDR (RET_CODE_ADDR + RET_CODE_SIZE)
624 +
625 +#define FLAG_D (1 << 10)
626 +
627 +/* Syscalls used by the vesafb thread */
628 +static int vm86old(struct vm86_struct __user* v86)
629 +{
630 + long res;
631 + __asm__ volatile ("push %%ebx; movl %2, %%ebx ; int $0x80 ; pop %%ebx"
632 + : "=a" (res)
633 + : "0" (__NR_vm86old), "ri" ((long)(v86)) : "memory");
634 +
635 + if ((unsigned long)(res) >= (unsigned long)(-MAX_ERRNO)) {
636 + errno = -res;
637 + res = -1;
638 + }
639 + return (int)res;
640 +}
641 +
642 +static int ioperm(unsigned long a, unsigned long b, unsigned long c)
643 +{
644 + long res;
645 + __asm__ volatile ("push %%ebx; movl %2, %%ebx ; int $0x80 ; pop %%ebx"
646 + : "=a" (res)
647 + : "0" (__NR_ioperm), "ri" ((long)(a)), "c" ((long)(b)),
648 + "d" ((long)(c)) : "memory");
649 +
650 + if ((unsigned long)(res) >= (unsigned long)(-MAX_ERRNO)) {
651 + errno = -res;
652 + res = -1;
653 + }
654 + return (int)res;
655 +}
656 +
657 +/* Segment prefix opcodes */
658 +enum {
659 + P_CS = 0x2e,
660 + P_SS = 0x36,
661 + P_DS = 0x3e,
662 + P_ES = 0x26,
663 + P_FS = 0x64,
664 + P_GS = 0x65
665 +};
666 +
667 +/* Emulated vm86 ins instruction */
668 +static void vm86_ins(int size)
669 +{
670 + u32 edx, edi;
671 + edx = vm86.regs.edx & 0xffff;
672 + edi = (vm86.regs.edi & 0xffff) + (u32)(vm86.regs.es << 4);
673 +
674 + if (vm86.regs.eflags & FLAG_D)
675 + asm volatile ("std\n");
676 + else
677 + asm volatile ("cld\n");
678 +
679 + switch (size) {
680 + case 4:
681 + asm volatile ("insl\n" : "=D" (edi) : "d" (edx), "0" (edi));
682 + break;
683 + case 2:
684 + asm volatile ("insw\n" : "=D" (edi) : "d" (edx), "0" (edi));
685 + break;
686 + case 1:
687 + asm volatile ("insb\n" : "=D" (edi) : "d" (edx), "0" (edi));
688 + break;
689 + }
690 +
691 + if (vm86.regs.eflags & FLAG_D)
692 + asm volatile ("cld\n");
693 +
694 + edi -= (u32)(vm86.regs.es << 4);
695 +
696 + vm86.regs.edi &= 0xffff0000;
697 + vm86.regs.edi |= edi & 0xffff;
698 +}
699 +
700 +static void vm86_rep_ins(int size)
701 +{
702 + u16 cx = vm86.regs.ecx;
703 + while (cx--)
704 + vm86_ins(size);
705 +
706 + vm86.regs.ecx &= 0xffff0000;
707 +}
708 +
709 +/* Emulated vm86 outs instruction */
710 +static void vm86_outs(int size, int segment)
711 +{
712 + u32 edx, esi, base;
713 +
714 + edx = vm86.regs.edx & 0xffff;
715 + esi = vm86.regs.esi & 0xffff;
716 +
717 + switch (segment) {
718 + case P_CS: base = vm86.regs.cs; break;
719 + case P_SS: base = vm86.regs.ss; break;
720 + case P_ES: base = vm86.regs.es; break;
721 + case P_FS: base = vm86.regs.fs; break;
722 + case P_GS: base = vm86.regs.gs; break;
723 + default: base = vm86.regs.ds; break;
724 + }
725 +
726 + esi += base << 4;
727 +
728 + if (vm86.regs.eflags & FLAG_D)
729 + asm volatile ("std\n");
730 + else
731 + asm volatile ("cld\n");
732 +
733 + switch (size) {
734 + case 4:
735 + asm volatile ("outsl\n" : "=S" (esi) : "d" (edx), "0" (esi));
736 + break;
737 + case 2:
738 + asm volatile ("outsw\n" : "=S" (esi) : "d" (edx), "0" (esi));
739 + break;
740 + case 1:
741 + asm volatile ("outsb\n" : "=S" (esi) : "d" (edx), "0" (esi));
742 + break;
743 + }
744 +
745 + if (vm86.regs.eflags & FLAG_D)
746 + asm volatile ("cld");
747 +
748 + esi -= base << 4;
749 + vm86.regs.esi &= 0xffff0000;
750 + vm86.regs.esi |= (esi & 0xffff);
751 +}
752 +
753 +static void vm86_rep_outs(int size, int segment)
754 +{
755 + u16 cx = vm86.regs.ecx;
756 + while (cx--)
757 + vm86_outs(size, segment);
758 +
759 + vm86.regs.ecx &= 0xffff0000;
760 +}
761 +
762 +static int vm86_do_unknown(void)
763 +{
764 + u8 data32 = 0, segment = P_DS, rep = 0;
765 + u8 *instr;
766 + int ret = 0, i = 0;
767 +
768 + instr = (u8*)((vm86.regs.cs << 4) + vm86.regs.eip);
769 +
770 + while (1) {
771 + switch(instr[i]) {
772 + case 0x66: /* operand size prefix */
773 + data32 = 1 - data32;
774 + i++;
775 + break;
776 + case 0xf2: /* repnz */
777 + case 0xf3: /* rep */
778 + rep = 1;
779 + i++;
780 + break;
781 + case P_CS: /* segment prefix */
782 + case P_SS:
783 + case P_DS:
784 + case P_ES:
785 + case P_FS:
786 + case P_GS:
787 + segment = instr[i];
788 + i++;
789 + break;
790 + case 0xf0: /* LOCK - ignored */
791 + case 0x67: /* address size prefix - ignored */
792 + i++;
793 + break;
794 + case 0x6c: /* insb */
795 + if (rep)
796 + vm86_rep_ins(1);
797 + else
798 + vm86_ins(1);
799 + i++;
800 + goto out;
801 + case 0x6d: /* insw / insd */
802 + if (rep) {
803 + if (data32)
804 + vm86_rep_ins(4);
805 + else
806 + vm86_rep_ins(2);
807 + } else {
808 + if (data32)
809 + vm86_ins(4);
810 + else
811 + vm86_ins(2);
812 + }
813 + i++;
814 + goto out;
815 + case 0x6e: /* outsb */
816 + if (rep)
817 + vm86_rep_outs(1, segment);
818 + else
819 + vm86_outs(1, segment);
820 + i++;
821 + goto out;
822 + case 0x6f: /* outsw / outsd */
823 + if (rep) {
824 + if (data32)
825 + vm86_rep_outs(4, segment);
826 + else
827 + vm86_rep_outs(2, segment);
828 + } else {
829 + if (data32)
830 + vm86_outs(4, segment);
831 + else
832 + vm86_outs(2, segment);
833 + }
834 + i++;
835 + goto out;
836 + case 0xe4: /* inb xx */
837 + asm volatile (
838 + "inb %w1, %b0"
839 + : "=a" (vm86.regs.eax)
840 + : "d" (instr[i+1]), "0" (vm86.regs.eax));
841 + i += 2;
842 + goto out;
843 + case 0xe5: /* inw xx / ind xx */
844 + if (data32) {
845 + asm volatile (
846 + "inl %w1, %0"
847 + : "=a" (vm86.regs.eax)
848 + : "d" (instr[i+1]),
849 + "0" (vm86.regs.eax));
850 + } else {
851 + asm volatile (
852 + "inw %w1, %w0"
853 + : "=a" (vm86.regs.eax)
854 + : "d" (instr[i+1]),
855 + "0" (vm86.regs.eax));
856 + }
857 + i += 2;
858 + goto out;
859 +
860 + case 0xec: /* inb dx */
861 + asm volatile (
862 + "inb %w1, %b0"
863 + : "=a" (vm86.regs.eax)
864 + : "d" (vm86.regs.edx), "0" (vm86.regs.eax));
865 + i++;
866 + goto out;
867 + case 0xed: /* inw dx / ind dx */
868 + if (data32) {
869 + asm volatile (
870 + "inl %w1, %0"
871 + : "=a" (vm86.regs.eax)
872 + : "d" (vm86.regs.edx));
873 + } else {
874 + asm volatile (
875 + "inw %w1, %w0"
876 + : "=a" (vm86.regs.eax)
877 + : "d" (vm86.regs.edx));
878 + }
879 + i++;
880 + goto out;
881 + case 0xe6: /* outb xx */
882 + asm volatile (
883 + "outb %b0, %w1"
884 + : /* no return value */
885 + : "a" (vm86.regs.eax), "d" (instr[i+1]));
886 + i += 2;
887 + goto out;
888 + case 0xe7: /* outw xx / outd xx */
889 + if (data32) {
890 + asm volatile (
891 + "outl %0, %w1"
892 + : /* no return value */
893 + : "a" (vm86.regs.eax),
894 + "d" (instr[i+1]));
895 + } else {
896 + asm volatile (
897 + "outw %w0, %w1"
898 + : /* no return value */
899 + : "a" (vm86.regs.eax),
900 + "d" (instr[i+1]));
901 + }
902 + i += 2;
903 + goto out;
904 + case 0xee: /* outb dx */
905 + asm volatile (
906 + "outb %b0, %w1"
907 + : /* no return value */
908 + : "a" (vm86.regs.eax), "d" (vm86.regs.edx));
909 + i++;
910 + goto out;
911 + case 0xef: /* outw dx / outd dx */
912 + if (data32) {
913 + asm volatile (
914 + "outl %0, %w1"
915 + : /* no return value */
916 + : "a" (vm86.regs.eax),
917 + "d" (vm86.regs.edx));
918 + } else {
919 + asm volatile (
920 + "outw %w0, %w1"
921 + : /* no return value */
922 + : "a" (vm86.regs.eax),
923 + "d" (vm86.regs.edx));
924 + }
925 + i++;
926 + goto out;
927 + default:
928 + printk(KERN_ERR "vesafb: BUG, opcode 0x%x emulation "
929 + "not supported (EIP: 0x%lx)\n",
930 + instr[i], (u32)(vm86.regs.cs << 4) +
931 + vm86.regs.eip);
932 + ret = 1;
933 + goto out;
934 + }
935 + }
936 +out: vm86.regs.eip += i;
937 + return ret;
938 +}
939 +
940 +void vesafb_do_vm86(struct vm86_regs *regs)
941 +{
942 + unsigned int ret;
943 + u8 *retcode = (void*)RET_CODE_ADDR;
944 +
945 + memset(&vm86,0,sizeof(vm86));
946 + memcpy(&vm86.regs, regs, sizeof(struct vm86_regs));
947 +
948 + /* The return code */
949 + retcode[0] = 0xcd; /* int opcode */
950 + retcode[1] = 0xff; /* int number (255) */
951 +
952 + /* We use int 0xff to get back to protected mode */
953 + memset(&vm86.int_revectored, 0, sizeof(vm86.int_revectored));
954 + ((unsigned char *)&vm86.int_revectored)[0xff / 8] |= (1 << (0xff % 8));
955 +
956 + /*
957 + * We want to call int 0x10, so we set:
958 + * CS = 0x42 = 0x10 * 4 + 2
959 + * IP = 0x40 = 0x10 * 4
960 + * and SS:ESP. It's up to the caller to set the rest of the registers.
961 + */
962 + vm86.regs.eflags = DEFAULT_VM86_FLAGS;
963 + vm86.regs.cs = *(unsigned short *)0x42;
964 + vm86.regs.eip = *(unsigned short *)0x40;
965 + vm86.regs.ss = (STACK_ADDR >> 4);
966 + vm86.regs.esp = ((STACK_ADDR & 0x0000f) + STACK_SIZE);
967 +
968 + /* These will be fetched off the stack when we come to an iret in the
969 + * int's 0x10 code. */
970 + VM86_PUSHW(DEFAULT_VM86_FLAGS);
971 + VM86_PUSHW((RET_CODE_ADDR >> 4)); /* return code segment */
972 + VM86_PUSHW((RET_CODE_ADDR & 0x0000f)); /* return code offset */
973 +
974 + while(1) {
975 + ret = vm86old(&vm86);
976 +
977 + if (VM86_TYPE(ret) == VM86_INTx) {
978 + int vint = VM86_ARG(ret);
979 +
980 + /* If exit from vm86 was caused by int 0xff, then
981 + * we're done.. */
982 + if (vint == 0xff)
983 + goto out;
984 +
985 + /* .. otherwise, we have to call the int handler
986 + * manually */
987 + VM86_PUSHW(vm86.regs.eflags);
988 + VM86_PUSHW(vm86.regs.cs);
989 + VM86_PUSHW(vm86.regs.eip);
990 +
991 + vm86.regs.cs = *(u16 *)((vint << 2) + 2);
992 + vm86.regs.eip = *(u16 *)(vint << 2);
993 + vm86.regs.eflags &= ~(VIF_MASK | TF_MASK);
994 + } else if (VM86_TYPE(ret) == VM86_UNKNOWN) {
995 + if (vm86_do_unknown())
996 + goto out;
997 + } else {
998 + printk(KERN_ERR "vesafb: BUG, returned from "
999 + "vm86 with %x (EIP: 0x%lx)\n",
1000 + ret, (u32)(vm86.regs.cs << 4) +
1001 + vm86.regs.eip);
1002 + goto out;
1003 + }
1004 + }
1005 +
1006 +out: /* copy the registers' state back to the caller's struct */
1007 + memcpy(regs, &vm86.regs, sizeof(struct vm86_regs));
1008 +}
1009 +
1010 +static int vesafb_remap_pfn_range(unsigned long start, unsigned long end,
1011 + unsigned long pgoff, unsigned long prot,
1012 + int type)
1013 +{
1014 + struct vm_area_struct *vma;
1015 + struct mm_struct *mm = current->mm;
1016 + int ret = 0;
1017 +
1018 + vma = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL);
1019 + if (!vma)
1020 + return -ENOMEM;
1021 + memset(vma, 0, sizeof(*vma));
1022 + down_write(&mm->mmap_sem);
1023 + vma->vm_mm = mm;
1024 + vma->vm_start = start;
1025 + vma->vm_end = end;
1026 + vma->vm_flags = VM_READ | VM_WRITE | VM_EXEC;
1027 + vma->vm_flags |= mm->def_flags;
1028 + vma->vm_page_prot.pgprot = prot;
1029 + vma->vm_pgoff = pgoff;
1030 +
1031 + if ((ret = insert_vm_struct(mm, vma))) {
1032 + up_write(&mm->mmap_sem);
1033 + kmem_cache_free(vm_area_cachep, vma);
1034 + return ret;
1035 + }
1036 +
1037 + if (type) {
1038 + ret = zeromap_page_range(vma,
1039 + vma->vm_start,
1040 + vma->vm_end - vma->vm_start,
1041 + vma->vm_page_prot);
1042 + } else {
1043 + vma->vm_flags |= VM_SHARED;
1044 + ret = remap_pfn_range(vma,
1045 + vma->vm_start,
1046 + vma->vm_pgoff,
1047 + vma->vm_end - vma->vm_start,
1048 + vma->vm_page_prot);
1049 + }
1050 + up_write(&mm->mmap_sem);
1051 + return ret;
1052 +}
1053 +
1054 +static inline int vesafb_init_mem(void)
1055 +{
1056 + int ret = 0;
1057 +
1058 + /* The memory chunks we're remapping here should be multiples
1059 + * of PAGE_SIZE. */
1060 + ret += vesafb_remap_pfn_range(0x00000, IVTBDA_SIZE, 0,
1061 + PROT_READ | PROT_EXEC | PROT_WRITE, 0);
1062 + ret += vesafb_remap_pfn_range(IVTBDA_SIZE, REAL_MEM_SIZE, 0,
1063 + PROT_READ | PROT_EXEC | PROT_WRITE, 1);
1064 + ret += vesafb_remap_pfn_range(0x9f000, 0x100000,
1065 + 0x9f000 >> PAGE_SHIFT,
1066 + PROT_READ | PROT_EXEC | PROT_WRITE, 0);
1067 + if (ret)
1068 + printk(KERN_ERR "vesafb thread: memory remapping failed\n");
1069 +
1070 + return ret;
1071 +}
1072 +
1073 +#define vesafb_get_string(str) \
1074 +{ \
1075 + /* The address is in the form ssssoooo, where oooo = offset, \
1076 + * ssss = segment */ \
1077 + addr = ((p_vbe(tsk->buf)->str & 0xffff0000) >> 12) + \
1078 + (p_vbe(tsk->buf)->str & 0x0000ffff); \
1079 + \
1080 + /* The data is in ROM which is shared between processes, so we \
1081 + * just translate the real mode address into one visible from \
1082 + * kernel space */ \
1083 + if (addr >= 0xa0000) { \
1084 + p_vbe(tsk->buf)->str = (u32) __va(addr); \
1085 + \
1086 + /* The data is in the buffer, we just have to convert the \
1087 + * address so that it points into the buffer user provided. */ \
1088 + } else if (addr > BUF_ADDR && addr < BUF_ADDR + \
1089 + sizeof(struct vesafb_vbe_ib)) { \
1090 + addr -= BUF_ADDR; \
1091 + p_vbe(tsk->buf)->str = (u32) (tsk->buf + addr); \
1092 + \
1093 + /* This should never happen: someone was insane enough to put \
1094 + * the data somewhere in RAM.. */ \
1095 + } else { \
1096 + p_vbe(tsk->buf)->str = (u32) ""; \
1097 + } \
1098 +}
1099 +
1100 +void vesafb_handle_getvbeib(struct vesafb_task *tsk)
1101 +{
1102 + int addr, res;
1103 +
1104 + tsk->regs.es = (BUF_ADDR >> 4);
1105 + tsk->regs.edi = (BUF_ADDR & 0x000f);
1106 + strncpy(p_vbe(BUF_ADDR)->vbe_signature, "VBE2", 4);
1107 +
1108 + vesafb_do_vm86(&tsk->regs);
1109 + memcpy(tsk->buf, (void*)(BUF_ADDR), sizeof(struct vesafb_vbe_ib));
1110 +
1111 + /* The OEM fields were not defined prior to VBE 2.0 */
1112 + if (p_vbe(tsk->buf)->vbe_version >= 0x200) {
1113 + vesafb_get_string(oem_string_ptr);
1114 + vesafb_get_string(oem_vendor_name_ptr);
1115 + vesafb_get_string(oem_product_name_ptr);
1116 + vesafb_get_string(oem_product_rev_ptr);
1117 + }
1118 +
1119 + /* This is basically the same as vesafb_get_string() */
1120 + addr = ((p_vbe(tsk->buf)->mode_list_ptr & 0xffff0000) >> 12) +
1121 + (p_vbe(tsk->buf)->mode_list_ptr & 0x0000ffff);
1122 +
1123 + if (addr >= 0xa0000) {
1124 + p_vbe(tsk->buf)->mode_list_ptr = (u32) __va(addr);
1125 + } else if (addr > BUF_ADDR && addr < BUF_ADDR +
1126 + sizeof(struct vesafb_vbe_ib)) {
1127 + addr -= BUF_ADDR;
1128 + p_vbe(tsk->buf)->mode_list_ptr = (u32) (tsk->buf + addr);
1129 + } else {
1130 + res = 0;
1131 + printk(KERN_WARNING "vesafb: warning, copying modelist "
1132 + "from somewhere in RAM!\n");
1133 + while (*(u16*)(addr+res) != 0xffff &&
1134 + res < (sizeof(p_vbe(tsk->buf)->reserved) - 2)) {
1135 + *(u16*) ((u32)&(p_vbe(tsk->buf)->reserved) + res) =
1136 + *(u16*)(addr+res);
1137 + res += 2;
1138 + }
1139 + *(u16*) ((u32)&(p_vbe(tsk->buf)->reserved) + res) = 0xffff;
1140 + }
1141 +}
1142 +
1143 +int vesafb_handle_tasks(void)
1144 +{
1145 + struct vesafb_task *tsk;
1146 + struct list_head *curr, *next;
1147 + int ret = 0;
1148 +
1149 + down(&vesafb_task_list_sem);
1150 + list_for_each_safe(curr, next, &vesafb_task_list) {
1151 + tsk = list_entry(curr, struct vesafb_task, node);
1152 +
1153 + if (tsk->flags & TF_EXIT) {
1154 + ret = 1;
1155 + goto task_done;
1156 + }
1157 + if (tsk->flags & TF_GETVBEIB) {
1158 + vesafb_handle_getvbeib(tsk);
1159 + goto task_done;
1160 + }
1161 + /* Do we need to store a pointer to the buffer in ES:EDI? */
1162 + if (tsk->flags & TF_BUF_DI) {
1163 + tsk->regs.es = (BUF_ADDR >> 4);
1164 + tsk->regs.edi = (BUF_ADDR & 0x000f);
1165 + }
1166 + /* Sometimes the pointer has to be in ES:EBX. */
1167 + if (tsk->flags & TF_BUF_BX) {
1168 + tsk->regs.es = (BUF_ADDR >> 4);
1169 + tsk->regs.ebx = (BUF_ADDR & 0x000f);
1170 + }
1171 + if (tsk->flags & (TF_BUF_DI | TF_BUF_BX))
1172 + memcpy((void*)BUF_ADDR, tsk->buf, tsk->buf_len);
1173 +
1174 + vesafb_do_vm86(&tsk->regs);
1175 +
1176 + if (tsk->flags & TF_RETURN_BUF)
1177 + memcpy(tsk->buf, (void*)BUF_ADDR, tsk->buf_len);
1178 +
1179 +task_done: list_del(curr);
1180 + complete(&tsk->done);
1181 + }
1182 +
1183 + /* If we're going to kill this thread, don't allow any elements
1184 + * to be added to the task list. */
1185 + if (!ret)
1186 + up(&vesafb_task_list_sem);
1187 +
1188 + return ret;
1189 +}
1190 +
1191 +/*
1192 + * This 'hybrid' thread serves as a backend for vesafb-tng, handling all vm86
1193 + * calls. It is started as a kernel thread. It then creates its own mm struct,
1194 + * thus separating itself from any userspace processes. At this moment, it
1195 + * stops being a kernel thread (kernel threads have mm = NULL) and becomes
1196 + * a 'hybrid' thread -- one that has full access to kernel space, yet runs
1197 + * with its own address space.
1198 + *
1199 + * This is necessary because in order to make vm86 calls some parts of the
1200 + * first 1MB of RAM have to be setup to mimic the real mode. These are:
1201 + * - interrupt vector table [0x00000-0x003ff]
1202 + * - BIOS data area [0x00400-0x004ff]
1203 + * - Extended BIOS data area [0x9fc00-0x9ffff]
1204 + * - the video RAM [0xa0000-0xbffff]
1205 + * - video BIOS [0xc0000-0xcffff]
1206 + * - motherboard BIOS [0xf0000-0xfffff]
1207 + */
1208 +int vesafb_thread(void *unused)
1209 +{
1210 + int err = 0;
1211 +
1212 + set_fs(KERNEL_DS);
1213 + daemonize("vesafb");
1214 +
1215 + if (set_new_mm()) {
1216 + err = -ENOMEM;
1217 + goto thr_end;
1218 + }
1219 + if (vesafb_init_mem()) {
1220 + err = -ENOMEM;
1221 + goto thr_end;
1222 + }
1223 +
1224 + DPRINTK("started vesafb thread\n");
1225 +
1226 + /* Having an IO bitmap makes things faster as we avoid GPFs
1227 + * when running vm86 code. We can live if it fails, though,
1228 + * so don't bother checking for errors. */
1229 + ioperm(0,1024,1);
1230 + set_user_nice(current, -10);
1231 +
1232 + complete(&vesafb_th_completion);
1233 +
1234 + while (1) {
1235 + if (vesafb_handle_tasks())
1236 + break;
1237 + wait_event_interruptible(vesafb_wait,
1238 + !list_empty(&vesafb_task_list));
1239 + try_to_freeze();
1240 + }
1241 +
1242 +out: DPRINTK("exiting the vesafb thread\n");
1243 + vesafb_pid = -1;
1244 +
1245 + /* Now that all callers know this thread is no longer running
1246 + * (pid < 0), allow them to continue. */
1247 + up(&vesafb_task_list_sem);
1248 + return err;
1249 +thr_end:
1250 + down(&vesafb_task_list_sem);
1251 + complete(&vesafb_th_completion);
1252 + goto out;
1253 +}
1254 +
1255 +int vesafb_queue_task(struct vesafb_task *tsk)
1256 +{
1257 + down(&vesafb_task_list_sem);
1258 + if (vesafb_pid < 0)
1259 + return -1;
1260 + list_add_tail(&tsk->node, &vesafb_task_list);
1261 + up(&vesafb_task_list_sem);
1262 + wake_up(&vesafb_wait);
1263 + return 0;
1264 +}
1265 +
1266 +int vesafb_wait_for_thread(void)
1267 +{
1268 + /* PID 0 means that the thread is still initializing. */
1269 + if (vesafb_pid < 0)
1270 + return -1;
1271 + wait_for_completion(&vesafb_th_completion);
1272 + return 0;
1273 +}
1274 +
1275 +int __init vesafb_init_thread(void)
1276 +{
1277 + vesafb_pid = kernel_thread(vesafb_thread,NULL,0);
1278 + return 0;
1279 +}
1280 +
1281 +#ifdef MODULE
1282 +void __exit vesafb_kill_thread(void)
1283 +{
1284 + struct vesafb_task *tsk;
1285 + if (vesafb_pid <= 0)
1286 + return;
1287 +
1288 + vesafb_create_task(tsk);
1289 + if (!tsk)
1290 + return;
1291 + tsk->flags |= TF_EXIT;
1292 + vesafb_queue_task(tsk);
1293 + vesafb_wait_for_task(tsk);
1294 + kfree(tsk);
1295 + return;
1296 +}
1297 +module_exit(vesafb_kill_thread);
1298 +#endif
1299 +module_init(vesafb_init_thread);
1300 +
1301 +EXPORT_SYMBOL_GPL(vesafb_queue_task);
1302 +EXPORT_SYMBOL_GPL(vesafb_wait_for_thread);
1303 +
1304 +MODULE_LICENSE("GPL");
1305 +MODULE_AUTHOR("Michal Januszewski");
1306 +
1307 Index: linux-git/drivers/video/vesafb-tng.c
1308 ===================================================================
1309 --- /dev/null
1310 +++ linux-git/drivers/video/vesafb-tng.c
1311 @@ -0,0 +1,1586 @@
1312 +/*
1313 + * Framebuffer driver for VBE 2.0+ compliant graphic boards
1314 + *
1315 + * (c) 2004-2006 Michal Januszewski <spock@gentoo.org>
1316 + * Based upon vesafb code by Gerd Knorr <kraxel@goldbach.in-berlin.de>
1317 + *
1318 + */
1319 +
1320 +#include <linux/module.h>
1321 +#include <linux/kernel.h>
1322 +#include <linux/errno.h>
1323 +#include <linux/string.h>
1324 +#include <linux/mm.h>
1325 +#include <linux/tty.h>
1326 +#include <linux/delay.h>
1327 +#include <linux/fb.h>
1328 +#include <linux/ioport.h>
1329 +#include <linux/init.h>
1330 +#include <linux/proc_fs.h>
1331 +#include <linux/completion.h>
1332 +#include <linux/platform_device.h>
1333 +#include <video/edid.h>
1334 +#include <video/vesa.h>
1335 +#include <video/vga.h>
1336 +#include <asm/io.h>
1337 +#include <asm/mtrr.h>
1338 +#include <asm/page.h>
1339 +#include <asm/pgtable.h>
1340 +#include "edid.h"
1341 +
1342 +#define dac_reg (0x3c8)
1343 +#define dac_val (0x3c9)
1344 +
1345 +#define VESAFB_NEED_EXACT_RES 1
1346 +#define VESAFB_NEED_EXACT_DEPTH 2
1347 +
1348 +/* --------------------------------------------------------------------- */
1349 +
1350 +static struct fb_var_screeninfo vesafb_defined __initdata = {
1351 + .activate = FB_ACTIVATE_NOW,
1352 + .height = 0,
1353 + .width = 0,
1354 + .right_margin = 32,
1355 + .upper_margin = 16,
1356 + .lower_margin = 4,
1357 + .vsync_len = 4,
1358 + .vmode = FB_VMODE_NONINTERLACED,
1359 +};
1360 +
1361 +static struct fb_fix_screeninfo vesafb_fix __initdata = {
1362 + .id = "VESA VGA",
1363 + .type = FB_TYPE_PACKED_PIXELS,
1364 + .accel = FB_ACCEL_NONE,
1365 +};
1366 +
1367 +static int mtrr = 0; /* disable mtrr by default */
1368 +static int blank = 1; /* enable blanking by default */
1369 +static int ypan = 0; /* 0 - nothing, 1 - ypan, 2 - ywrap */
1370 +static int pmi_setpal = 1; /* pmi for palette changes */
1371 +static u16 *pmi_base = NULL; /* protected mode interface location */
1372 +static void (*pmi_start)(void) = NULL;
1373 +static void (*pmi_pal)(void) = NULL;
1374 +static struct vesafb_vbe_ib vbe_ib;
1375 +static struct vesafb_mode_ib *vbe_modes;
1376 +static int vbe_modes_cnt = 0;
1377 +static struct fb_info *vesafb_info = NULL;
1378 +static int nocrtc = 0; /* ignore CRTC settings */
1379 +static int noedid __initdata = 0; /* don't try DDC transfers */
1380 +static int vram_remap __initdata = 0; /* set amount of memory to be used */
1381 +static int vram_total __initdata = 0; /* set total amount of memory */
1382 +static u16 maxclk __initdata = 0; /* maximum pixel clock */
1383 +static u16 maxvf __initdata = 0; /* maximum vertical frequency */
1384 +static u16 maxhf __initdata = 0; /* maximum horizontal frequency */
1385 +static int gtf __initdata = 0; /* forces use of the GTF */
1386 +static char *mode_option __initdata = NULL;
1387 +static u16 vbemode __initdata = 0;
1388 +
1389 +/* --------------------------------------------------------------------- */
1390 +
1391 +static int vesafb_find_vbe_mode(int xres, int yres, int depth,
1392 + unsigned char flags)
1393 +{
1394 + int i, match = -1, h = 0, d = 0x7fffffff;
1395 +
1396 + for (i = 0; i < vbe_modes_cnt; i++) {
1397 + h = abs(vbe_modes[i].x_res - xres) +
1398 + abs(vbe_modes[i].y_res - yres) +
1399 + abs(depth - vbe_modes[i].depth);
1400 + if (h == 0)
1401 + return i;
1402 + if (h < d || (h == d && vbe_modes[i].depth > depth)) {
1403 + d = h;
1404 + match = i;
1405 + }
1406 + }
1407 + i = 1;
1408 +
1409 + if (flags & VESAFB_NEED_EXACT_DEPTH && vbe_modes[match].depth != depth)
1410 + i = 0;
1411 + if (flags & VESAFB_NEED_EXACT_RES && d > 24)
1412 + i = 0;
1413 + if (i != 0)
1414 + return match;
1415 + else
1416 + return -1;
1417 +}
1418 +
1419 +static int vesafb_pan_display(struct fb_var_screeninfo *var,
1420 + struct fb_info *info)
1421 +{
1422 + int offset;
1423 +
1424 + offset = (var->yoffset * info->fix.line_length + var->xoffset) / 4;
1425 +
1426 + /* It turns out it's not the best idea to do panning via vm86,
1427 + * so we only allow it if we have a PMI. */
1428 + if (pmi_start) {
1429 + __asm__ __volatile__(
1430 + "call *(%%edi)"
1431 + : /* no return value */
1432 + : "a" (0x4f07), /* EAX */
1433 + "b" (0), /* EBX */
1434 + "c" (offset), /* ECX */
1435 + "d" (offset >> 16), /* EDX */
1436 + "D" (&pmi_start)); /* EDI */
1437 + }
1438 + return 0;
1439 +}
1440 +
1441 +static int vesafb_blank(int blank, struct fb_info *info)
1442 +{
1443 + struct vesafb_task *tsk;
1444 + int err = 1;
1445 +
1446 + if (vbe_ib.capabilities & VBE_CAP_VGACOMPAT) {
1447 + int loop = 10000;
1448 + u8 seq = 0, crtc17 = 0;
1449 +
1450 + if (blank == FB_BLANK_POWERDOWN) {
1451 + seq = 0x20;
1452 + crtc17 = 0x00;
1453 + err = 0;
1454 + } else {
1455 + seq = 0x00;
1456 + crtc17 = 0x80;
1457 + err = (blank == FB_BLANK_UNBLANK) ? 0 : -EINVAL;
1458 + }
1459 +
1460 + vga_wseq(NULL, 0x00, 0x01);
1461 + seq |= vga_rseq(NULL, 0x01) & ~0x20;
1462 + vga_wseq(NULL, 0x00, seq);
1463 +
1464 + crtc17 |= vga_rcrt(NULL, 0x17) & ~0x80;
1465 + while (loop--);
1466 + vga_wcrt(NULL, 0x17, crtc17);
1467 + vga_wseq(NULL, 0x00, 0x03);
1468 + } else {
1469 + vesafb_create_task (tsk);
1470 + if (!tsk)
1471 + return -ENOMEM;
1472 + tsk->regs.eax = 0x4f10;
1473 + switch (blank) {
1474 + case FB_BLANK_UNBLANK:
1475 + tsk->regs.ebx = 0x0001;
1476 + break;
1477 + case FB_BLANK_NORMAL:
1478 + tsk->regs.ebx = 0x0101; /* standby */
1479 + break;
1480 + case FB_BLANK_POWERDOWN:
1481 + tsk->regs.ebx = 0x0401; /* powerdown */
1482 + break;
1483 + default:
1484 + goto out;
1485 + }
1486 + tsk->flags = TF_CALL;
1487 + if (!vesafb_queue_task (tsk))
1488 + vesafb_wait_for_task(tsk);
1489 +
1490 + if ((tsk->regs.eax & 0xffff) == 0x004f)
1491 + err = 0;
1492 +out: kfree(tsk);
1493 + }
1494 + return err;
1495 +}
1496 +
1497 +static int vesafb_setpalette(struct vesafb_pal_entry *entries, int count,
1498 + int start, struct fb_info *info)
1499 +{
1500 + struct vesafb_task *tsk;
1501 + int i = ((struct vesafb_par*)info->par)->mode_idx;
1502 + int ret = 0;
1503 +
1504 + /* We support palette modifications for 8 bpp modes only, so
1505 + * there can never be more than 256 entries. */
1506 + if (start + count > 256)
1507 + return -EINVAL;
1508 +
1509 + /* Use VGA registers if mode is VGA-compatible. */
1510 + if (i >= 0 && i < vbe_modes_cnt &&
1511 + vbe_modes[i].mode_attr & VBE_MODE_VGACOMPAT) {
1512 + for (i = 0; i < count; i++) {
1513 + outb_p(start + i, dac_reg);
1514 + outb_p(entries[i].red, dac_val);
1515 + outb_p(entries[i].green, dac_val);
1516 + outb_p(entries[i].blue, dac_val);
1517 + }
1518 + } else if (pmi_setpal) {
1519 + __asm__ __volatile__(
1520 + "call *(%%esi)"
1521 + : /* no return value */
1522 + : "a" (0x4f09), /* EAX */
1523 + "b" (0), /* EBX */
1524 + "c" (count), /* ECX */
1525 + "d" (start), /* EDX */
1526 + "D" (entries), /* EDI */
1527 + "S" (&pmi_pal)); /* ESI */
1528 + } else {
1529 + vesafb_create_task (tsk);
1530 + if (!tsk)
1531 + return -ENOMEM;
1532 + tsk->regs.eax = 0x4f09;
1533 + tsk->regs.ebx = 0x0;
1534 + tsk->regs.ecx = count;
1535 + tsk->regs.edx = start;
1536 + tsk->buf = entries;
1537 + tsk->buf_len = sizeof(struct vesafb_pal_entry) * count;
1538 + tsk->flags = TF_CALL | TF_BUF_DI;
1539 +
1540 + if (!vesafb_queue_task (tsk))
1541 + vesafb_wait_for_task(tsk);
1542 + if ((tsk->regs.eax & 0xffff) != 0x004f)
1543 + ret = 1;
1544 + kfree(tsk);
1545 + }
1546 + return ret;
1547 +}
1548 +
1549 +static int vesafb_setcolreg(unsigned regno, unsigned red, unsigned green,
1550 + unsigned blue, unsigned transp,
1551 + struct fb_info *info)
1552 +{
1553 + struct vesafb_pal_entry entry;
1554 + int shift = 16 - info->var.green.length;
1555 + int ret = 0;
1556 +
1557 + if (regno >= info->cmap.len)
1558 + return -EINVAL;
1559 +
1560 + if (info->var.bits_per_pixel == 8) {
1561 + entry.red = red >> shift;
1562 + entry.green = green >> shift;
1563 + entry.blue = blue >> shift;
1564 + entry.pad = 0;
1565 +
1566 + ret = vesafb_setpalette(&entry, 1, regno, info);
1567 + } else if (regno < 16) {
1568 + switch (info->var.bits_per_pixel) {
1569 + case 16:
1570 + if (info->var.red.offset == 10) {
1571 + /* 1:5:5:5 */
1572 + ((u32*) (info->pseudo_palette))[regno] =
1573 + ((red & 0xf800) >> 1) |
1574 + ((green & 0xf800) >> 6) |
1575 + ((blue & 0xf800) >> 11);
1576 + } else {
1577 + /* 0:5:6:5 */
1578 + ((u32*) (info->pseudo_palette))[regno] =
1579 + ((red & 0xf800) ) |
1580 + ((green & 0xfc00) >> 5) |
1581 + ((blue & 0xf800) >> 11);
1582 + }
1583 + break;
1584 +
1585 + case 24:
1586 + case 32:
1587 + red >>= 8;
1588 + green >>= 8;
1589 + blue >>= 8;
1590 + ((u32 *)(info->pseudo_palette))[regno] =
1591 + (red << info->var.red.offset) |
1592 + (green << info->var.green.offset) |
1593 + (blue << info->var.blue.offset);
1594 + break;
1595 + }
1596 + }
1597 + return ret;
1598 +}
1599 +
1600 +static int vesafb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
1601 +{
1602 + struct vesafb_pal_entry *entries;
1603 + int shift = 16 - info->var.green.length;
1604 + int i, ret = 0;
1605 +
1606 + if (info->var.bits_per_pixel == 8) {
1607 + if (cmap->start + cmap->len > info->cmap.start +
1608 + info->cmap.len || cmap->start < info->cmap.start)
1609 + return -EINVAL;
1610 +
1611 + entries = vmalloc(sizeof(struct vesafb_pal_entry) * cmap->len);
1612 + if (!entries)
1613 + return -ENOMEM;
1614 + for (i = 0; i < cmap->len; i++) {
1615 + entries[i].red = cmap->red[i] >> shift;
1616 + entries[i].green = cmap->green[i] >> shift;
1617 + entries[i].blue = cmap->blue[i] >> shift;
1618 + entries[i].pad = 0;
1619 + }
1620 + ret = vesafb_setpalette(entries, cmap->len, cmap->start, info);
1621 + vfree(entries);
1622 + } else {
1623 + /* For modes with bpp > 8, we only set the pseudo palette in
1624 + * the fb_info struct. We rely on vesafb_setcolreg to do all
1625 + * sanity checking. */
1626 + for (i = 0; i < cmap->len; i++) {
1627 + ret += vesafb_setcolreg(cmap->start + i, cmap->red[i],
1628 + cmap->green[i], cmap->blue[i],
1629 + 0, info);
1630 + }
1631 + }
1632 + return ret;
1633 +}
1634 +
1635 +static int vesafb_set_par(struct fb_info *info)
1636 +{
1637 + struct vesafb_par *par = (struct vesafb_par *) info->par;
1638 + struct vesafb_task *tsk;
1639 + struct vesafb_crtc_ib *crtc = NULL;
1640 + struct vesafb_mode_ib *mode = NULL;
1641 + int i, err = 0, depth = info->var.bits_per_pixel;
1642 +
1643 + if (depth > 8 && depth != 32)
1644 + depth = info->var.red.length + info->var.green.length +
1645 + info->var.blue.length;
1646 +
1647 + i = vesafb_find_vbe_mode(info->var.xres, info->var.yres, depth,
1648 + VESAFB_NEED_EXACT_RES |
1649 + VESAFB_NEED_EXACT_DEPTH);
1650 + if (i >= 0)
1651 + mode = &vbe_modes[i];
1652 + else
1653 + return -EINVAL;
1654 +
1655 + vesafb_create_task (tsk);
1656 + if (!tsk)
1657 + return -ENOMEM;
1658 + tsk->regs.eax = 0x4f02;
1659 + tsk->regs.ebx = mode->mode_id | 0x4000; /* use LFB */
1660 + tsk->flags = TF_CALL;
1661 +
1662 + if (vbe_ib.vbe_version >= 0x0300 && !nocrtc &&
1663 + info->var.pixclock != 0) {
1664 + tsk->regs.ebx |= 0x0800; /* use CRTC data */
1665 + tsk->flags |= TF_BUF_DI;
1666 + crtc = kmalloc(sizeof(struct vesafb_crtc_ib), GFP_KERNEL);
1667 + if (!crtc) {
1668 + err = -ENOMEM;
1669 + goto out;
1670 + }
1671 + crtc->horiz_start = info->var.xres + info->var.right_margin;
1672 + crtc->horiz_end = crtc->horiz_start + info->var.hsync_len;
1673 + crtc->horiz_total = crtc->horiz_end + info->var.left_margin;
1674 +
1675 + crtc->vert_start = info->var.yres + info->var.lower_margin;
1676 + crtc->vert_end = crtc->vert_start + info->var.vsync_len;
1677 + crtc->vert_total = crtc->vert_end + info->var.upper_margin;
1678 +
1679 + crtc->pixel_clock = PICOS2KHZ(info->var.pixclock) * 1000;
1680 + crtc->refresh_rate = (u16)(100 * (crtc->pixel_clock /
1681 + (crtc->vert_total * crtc->horiz_total)));
1682 + crtc->flags = 0;
1683 +
1684 + if (info->var.vmode & FB_VMODE_DOUBLE)
1685 + crtc->flags |= 0x1;
1686 + if (info->var.vmode & FB_VMODE_INTERLACED)
1687 + crtc->flags |= 0x2;
1688 + if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
1689 + crtc->flags |= 0x4;
1690 + if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
1691 + crtc->flags |= 0x8;
1692 + memcpy(&par->crtc, crtc, sizeof(struct vesafb_crtc_ib));
1693 + } else
1694 + memset(&par->crtc, 0, sizeof(struct vesafb_crtc_ib));
1695 +
1696 + tsk->buf = (void*)crtc;
1697 + tsk->buf_len = sizeof(struct vesafb_crtc_ib);
1698 +
1699 + if (vesafb_queue_task (tsk)) {
1700 + err = -EINVAL;
1701 + goto out;
1702 + }
1703 + vesafb_wait_for_task(tsk);
1704 +
1705 + if ((tsk->regs.eax & 0xffff) != 0x004f) {
1706 + printk(KERN_ERR "vesafb: mode switch failed (eax: 0x%lx)\n",
1707 + tsk->regs.eax);
1708 + err = -EINVAL;
1709 + goto out;
1710 + }
1711 + par->mode_idx = i;
1712 +
1713 + /* For 8bpp modes, always try to set the DAC to 8 bits. */
1714 + if (vbe_ib.capabilities & VBE_CAP_CAN_SWITCH_DAC &&
1715 + mode->bits_per_pixel <= 8) {
1716 + vesafb_reset_task(tsk);
1717 + tsk->flags = TF_CALL;
1718 + tsk->regs.eax = 0x4f08;
1719 + tsk->regs.ebx = 0x0800;
1720 +
1721 + if (!vesafb_queue_task (tsk))
1722 + vesafb_wait_for_task(tsk);
1723 +
1724 + if ((tsk->regs.eax & 0xffff) != 0x004f ||
1725 + ((tsk->regs.ebx & 0xff00) >> 8) != 8) {
1726 + /* We've failed to set the DAC palette format -
1727 + * time to correct var. */
1728 + info->var.red.length = 6;
1729 + info->var.green.length = 6;
1730 + info->var.blue.length = 6;
1731 + }
1732 + }
1733 +
1734 + info->fix.visual = (info->var.bits_per_pixel == 8) ?
1735 + FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
1736 + info->fix.line_length = mode->bytes_per_scan_line;
1737 +
1738 + DPRINTK("set new mode %dx%d-%d (0x%x)\n",
1739 + info->var.xres, info->var.yres, info->var.bits_per_pixel,
1740 + mode->mode_id);
1741 +
1742 +out: if (crtc != NULL)
1743 + kfree(crtc);
1744 + kfree(tsk);
1745 +
1746 + return err;
1747 +}
1748 +
1749 +static void vesafb_setup_var(struct fb_var_screeninfo *var, struct fb_info *info,
1750 + struct vesafb_mode_ib *mode)
1751 +{
1752 + var->xres = mode->x_res;
1753 + var->yres = mode->y_res;
1754 + var->xres_virtual = mode->x_res;
1755 + var->yres_virtual = (ypan) ?
1756 + info->fix.smem_len / mode->bytes_per_scan_line :
1757 + mode->y_res;
1758 + var->xoffset = 0;
1759 + var->yoffset = 0;
1760 + var->bits_per_pixel = mode->bits_per_pixel;
1761 +
1762 + if (var->bits_per_pixel == 15)
1763 + var->bits_per_pixel = 16;
1764 +
1765 + if (var->bits_per_pixel > 8) {
1766 + var->red.offset = mode->red_off;
1767 + var->red.length = mode->red_len;
1768 + var->green.offset = mode->green_off;
1769 + var->green.length = mode->green_len;
1770 + var->blue.offset = mode->blue_off;
1771 + var->blue.length = mode->blue_len;
1772 + var->transp.offset = mode->rsvd_off;
1773 + var->transp.length = mode->rsvd_len;
1774 +
1775 + DPRINTK("directcolor: size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
1776 + mode->rsvd_len,
1777 + mode->red_len,
1778 + mode->green_len,
1779 + mode->blue_len,
1780 + mode->rsvd_off,
1781 + mode->red_off,
1782 + mode->green_off,
1783 + mode->blue_off);
1784 + } else {
1785 + var->red.offset = 0;
1786 + var->green.offset = 0;
1787 + var->blue.offset = 0;
1788 + var->transp.offset = 0;
1789 +
1790 + /* We're assuming that we can switch the DAC to 8 bits. If
1791 + * this proves to be incorrect, we'll update the fields
1792 + * later in set_par(). */
1793 + if (vbe_ib.capabilities & VBE_CAP_CAN_SWITCH_DAC) {
1794 + var->red.length = 8;
1795 + var->green.length = 8;
1796 + var->blue.length = 8;
1797 + var->transp.length = 0;
1798 + } else {
1799 + var->red.length = 6;
1800 + var->green.length = 6;
1801 + var->blue.length = 6;
1802 + var->transp.length = 0;
1803 + }
1804 + }
1805 +}
1806 +
1807 +static void inline vesafb_check_limits(struct fb_var_screeninfo *var,
1808 + struct fb_info *info)
1809 +{
1810 + struct fb_videomode *mode;
1811 +
1812 + if (!var->pixclock)
1813 + return;
1814 + if (vbe_ib.vbe_version < 0x0300) {
1815 + fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60, var, info);
1816 + return;
1817 + }
1818 + if (!fb_validate_mode(var, info))
1819 + return;
1820 + mode = fb_find_best_mode(var, &info->modelist);
1821 + if (mode) {
1822 + DPRINTK("find_best_mode: %d %d @ %d (vmode: %d)\n",
1823 + mode->xres, mode->yres, mode->refresh, mode->vmode);
1824 + if (mode->xres == var->xres && mode->yres == var->yres &&
1825 + !(mode->vmode & (FB_VMODE_INTERLACED | FB_VMODE_DOUBLE))) {
1826 + fb_videomode_to_var(var, mode);
1827 + return;
1828 + }
1829 + }
1830 + if (info->monspecs.gtf && !fb_get_mode(FB_MAXTIMINGS, 0, var, info))
1831 + return;
1832 + /* Use default refresh rate */
1833 + var->pixclock = 0;
1834 +}
1835 +
1836 +static int vesafb_check_var(struct fb_var_screeninfo *var,
1837 + struct fb_info *info)
1838 +{
1839 + int match = -1;
1840 + int depth = var->red.length + var->green.length + var->blue.length;
1841 +
1842 + /* Various apps will use bits_per_pixel to set the color depth,
1843 + * which is theoretically incorrect, but which we'll try to handle
1844 + * here. */
1845 + if (depth == 0 || abs(depth - var->bits_per_pixel) >= 8)
1846 + depth = var->bits_per_pixel;
1847 + match = vesafb_find_vbe_mode(var->xres, var->yres, depth,
1848 + VESAFB_NEED_EXACT_RES);
1849 +
1850 + if (match == -1) {
1851 + DPRINTK("vesafb: mode %dx%d-%d not found\n", var->xres,
1852 + var->yres, depth);
1853 + return -EINVAL;
1854 + }
1855 +
1856 + vesafb_setup_var(var, info, &vbe_modes[match]);
1857 + DPRINTK("found mode 0x%x (%dx%d-%dbpp)\n",
1858 + vbe_modes[match].mode_id, vbe_modes[match].x_res,
1859 + vbe_modes[match].y_res, vbe_modes[match].depth);
1860 +
1861 + /* Check whether we have remapped enough memory for this mode. */
1862 + if (var->yres * vbe_modes[match].bytes_per_scan_line >
1863 + info->fix.smem_len) {
1864 + return -EINVAL;
1865 + }
1866 +
1867 + if ((var->vmode & FB_VMODE_DOUBLE) &&
1868 + !(vbe_modes[match].mode_attr & 0x100))
1869 + var->vmode &= ~FB_VMODE_DOUBLE;
1870 + if ((var->vmode & FB_VMODE_INTERLACED) &&
1871 + !(vbe_modes[match].mode_attr & 0x200))
1872 + var->vmode &= ~FB_VMODE_INTERLACED;
1873 + vesafb_check_limits(var, info);
1874 + return 0;
1875 +}
1876 +
1877 +static int vesafb_open(struct fb_info *info, int user)
1878 +{
1879 + struct vesafb_task *tsk = NULL;
1880 + struct vesafb_par *par = info->par;
1881 + int cnt = atomic_read(&par->ref_count);
1882 +
1883 + if (!cnt) {
1884 + vesafb_create_task(tsk);
1885 + if (!tsk)
1886 + goto out;
1887 +
1888 + /* Get the VBE state buffer size. We want all available
1889 + * hardware state data (CL = 0x0f). */
1890 + tsk->regs.eax = 0x4f04;
1891 + tsk->regs.ecx = 0x000f;
1892 + tsk->regs.edx = 0x0000;
1893 + tsk->flags = TF_CALL;
1894 +
1895 + if (vesafb_queue_task(tsk))
1896 + goto out;
1897 +
1898 + vesafb_wait_for_task(tsk);
1899 +
1900 + if ((tsk->regs.eax & 0xffff) != 0x004f) {
1901 + printk(KERN_WARNING "vesafb: VBE state buffer size "
1902 + "cannot be determined (eax: 0x%lx)\n",
1903 + tsk->regs.eax);
1904 + goto out;
1905 + }
1906 +
1907 + par->vbe_state_size = 64 * (tsk->regs.ebx & 0xffff);
1908 + par->vbe_state = kzalloc(par->vbe_state_size, GFP_KERNEL);
1909 + if (!par->vbe_state)
1910 + goto out;
1911 +
1912 + vesafb_reset_task(tsk);
1913 + tsk->regs.eax = 0x4f04;
1914 + tsk->regs.ecx = 0x000f;
1915 + tsk->regs.edx = 0x0001;
1916 + tsk->flags = TF_CALL | TF_BUF_BX | TF_RETURN_BUF;
1917 + tsk->buf = (void*)(par->vbe_state);
1918 + tsk->buf_len = par->vbe_state_size;
1919 +
1920 + if (vesafb_queue_task(tsk))
1921 + goto getstate_failed;
1922 + vesafb_wait_for_task(tsk);
1923 +
1924 + if ((tsk->regs.eax & 0xffff) != 0x004f) {
1925 + printk(KERN_WARNING "vesafb: VBE get state call "
1926 + "failed (eax: 0x%lx)\n", tsk->regs.eax);
1927 + goto getstate_failed;
1928 + }
1929 + }
1930 +out:
1931 + atomic_inc(&par->ref_count);
1932 + if (tsk)
1933 + kfree(tsk);
1934 + return 0;
1935 +
1936 +getstate_failed:
1937 + kfree(par->vbe_state);
1938 + par->vbe_state = NULL;
1939 + par->vbe_state_size = 0;
1940 + goto out;
1941 +}
1942 +
1943 +static int vesafb_release(struct fb_info *info, int user)
1944 +{
1945 + struct vesafb_task *tsk = NULL;
1946 + struct vesafb_par *par = info->par;
1947 + int cnt = atomic_read(&par->ref_count);
1948 +
1949 + if (!cnt)
1950 + return -EINVAL;
1951 +
1952 + if (cnt == 1 && par->vbe_state && par->vbe_state_size) {
1953 + vesafb_create_task(tsk);
1954 + if (!tsk)
1955 + goto out;
1956 +
1957 + tsk->regs.eax = 0x0003;
1958 + tsk->regs.ebx = 0x0000;
1959 + tsk->flags = TF_CALL;
1960 +
1961 + if (vesafb_queue_task(tsk))
1962 + goto out;
1963 +
1964 + vesafb_wait_for_task(tsk);
1965 +
1966 + vesafb_reset_task(tsk);
1967 + tsk->regs.eax = 0x4f04;
1968 + tsk->regs.ecx = 0x000f;
1969 + tsk->regs.edx = 0x0002;
1970 + tsk->buf = (void*)(par->vbe_state);
1971 + tsk->buf_len = par->vbe_state_size;
1972 + tsk->flags = TF_CALL | TF_BUF_BX;
1973 +
1974 + if (vesafb_queue_task(tsk))
1975 + goto out;
1976 +
1977 + vesafb_wait_for_task(tsk);
1978 +
1979 + if ((tsk->regs.eax & 0xffff) != 0x004f)
1980 + printk(KERN_WARNING "vesafb: VBE state restore call "
1981 + "failed (eax: 0x%lx)\n",
1982 + tsk->regs.eax);
1983 + }
1984 +out:
1985 + atomic_dec(&par->ref_count);
1986 + if (tsk)
1987 + kfree(tsk);
1988 + return 0;
1989 +}
1990 +
1991 +static int __init vesafb_probe(struct platform_device *device);
1992 +
1993 +static struct fb_ops vesafb_ops = {
1994 + .owner = THIS_MODULE,
1995 + .fb_open = vesafb_open,
1996 + .fb_release = vesafb_release,
1997 + .fb_setcolreg = vesafb_setcolreg,
1998 + .fb_setcmap = vesafb_setcmap,
1999 + .fb_pan_display = vesafb_pan_display,
2000 + .fb_blank = vesafb_blank,
2001 + .fb_fillrect = cfb_fillrect,
2002 + .fb_copyarea = cfb_copyarea,
2003 + .fb_imageblit = cfb_imageblit,
2004 + .fb_check_var = vesafb_check_var,
2005 + .fb_set_par = vesafb_set_par
2006 +};
2007 +
2008 +static struct platform_driver vesafb_driver = {
2009 + .probe = vesafb_probe,
2010 + .driver = {
2011 + .name = "vesafb",
2012 + },
2013 +};
2014 +
2015 +static struct platform_device *vesafb_device;
2016 +
2017 +#ifndef MODULE
2018 +int __init vesafb_setup(char *options)
2019 +{
2020 + char *this_opt;
2021 +
2022 + if (!options || !*options)
2023 + return 0;
2024 +
2025 + DPRINTK("options %s\n",options);
2026 +
2027 + while ((this_opt = strsep(&options, ",")) != NULL) {
2028 + if (!*this_opt) continue;
2029 +
2030 + DPRINTK("this_opt: %s\n",this_opt);
2031 +
2032 + if (! strcmp(this_opt, "redraw"))
2033 + ypan=0;
2034 + else if (! strcmp(this_opt, "ypan"))
2035 + ypan=1;
2036 + else if (! strcmp(this_opt, "ywrap"))
2037 + ypan=2;
2038 + else if (! strcmp(this_opt, "vgapal"))
2039 + pmi_setpal=0;
2040 + else if (! strcmp(this_opt, "pmipal"))
2041 + pmi_setpal=1;
2042 + else if (! strncmp(this_opt, "mtrr:", 5))
2043 + mtrr = simple_strtoul(this_opt+5, NULL, 0);
2044 + else if (! strcmp(this_opt, "nomtrr"))
2045 + mtrr=0;
2046 + else if (! strcmp(this_opt, "nocrtc"))
2047 + nocrtc=1;
2048 + else if (! strcmp(this_opt, "noedid"))
2049 + noedid=1;
2050 + else if (! strcmp(this_opt, "noblank"))
2051 + blank=0;
2052 + else if (! strcmp(this_opt, "gtf"))
2053 + gtf=1;
2054 + else if (! strncmp(this_opt, "vtotal:", 7))
2055 + vram_total = simple_strtoul(this_opt + 7, NULL, 0);
2056 + else if (! strncmp(this_opt, "vremap:", 7))
2057 + vram_remap = simple_strtoul(this_opt + 7, NULL, 0);
2058 + else if (! strncmp(this_opt, "maxhf:", 6))
2059 + maxhf = simple_strtoul(this_opt + 6, NULL, 0);
2060 + else if (! strncmp(this_opt, "maxvf:", 6))
2061 + maxvf = simple_strtoul(this_opt + 6, NULL, 0);
2062 + else if (! strncmp(this_opt, "maxclk:", 7))
2063 + maxclk = simple_strtoul(this_opt + 7, NULL, 0);
2064 + else if (! strncmp(this_opt, "vbemode:", 8))
2065 + vbemode = simple_strtoul(this_opt + 8, NULL,0);
2066 + else if (this_opt[0] >= '0' && this_opt[0] <= '9') {
2067 + DPRINTK("mode_option: %s\n",this_opt);
2068 + mode_option = this_opt;
2069 + } else {
2070 + printk(KERN_WARNING
2071 + "vesafb: unrecognized option %s\n", this_opt);
2072 + }
2073 + }
2074 +
2075 + return 0;
2076 +}
2077 +#endif /* !MODULE */
2078 +
2079 +static int vesafb_read_proc_modes(char *buf, char **start, off_t offset,
2080 + int len, int *eof, void *private)
2081 +{
2082 + int clen = 0, i;
2083 +
2084 + for (i = 0; i < vbe_modes_cnt; i++) {
2085 + clen += min(snprintf(buf + clen, len - clen, "%dx%d-%d\n", vbe_modes[i].x_res,
2086 + vbe_modes[i].y_res, vbe_modes[i].depth), len - clen);
2087 + }
2088 + *eof = 1;
2089 + return clen;
2090 +}
2091 +
2092 +static int vesafb_read_proc_vbe_info(char *buf, char **start, off_t offset,
2093 + int len, int *eof, void *private)
2094 +{
2095 + int clen = 0;
2096 +
2097 + clen += min(snprintf(buf + clen, len, "Version: %d.%d\n",
2098 + ((vbe_ib.vbe_version & 0xff00) >> 8),
2099 + vbe_ib.vbe_version & 0xff), len);
2100 + clen += min(snprintf(buf + clen, len - clen, "Vendor: %s\n",
2101 + (char*)vbe_ib.oem_vendor_name_ptr), len - clen);
2102 + clen += min(snprintf(buf + clen, len - clen, "Product: %s\n",
2103 + (char*)vbe_ib.oem_product_name_ptr), len - clen);
2104 + clen += min(snprintf(buf + clen, len - clen, "OEM rev: %s\n",
2105 + (char*)vbe_ib.oem_product_rev_ptr), len - clen);
2106 + clen += min(snprintf(buf + clen, len - clen, "OEM string: %s\n",
2107 + (char*)vbe_ib.oem_string_ptr), len - clen);
2108 +
2109 + *eof = 1;
2110 + return clen;
2111 +}
2112 +
2113 +static int __init inline vesafb_vbe_getinfo(struct vesafb_task *tsk)
2114 +{
2115 + tsk->regs.eax = 0x4f00;
2116 + tsk->flags = TF_CALL | TF_GETVBEIB;
2117 + tsk->buf = &vbe_ib;
2118 + tsk->buf_len = sizeof(vbe_ib);
2119 + if (vesafb_queue_task (tsk))
2120 + return -EINVAL;
2121 + vesafb_wait_for_task(tsk);
2122 +
2123 + if (vbe_ib.vbe_version < 0x0200) {
2124 + printk(KERN_ERR "vesafb: Sorry, pre-VBE 2.0 cards are "
2125 + "not supported.\n");
2126 + return -EINVAL;
2127 + }
2128 +
2129 + if ((tsk->regs.eax & 0xffff) != 0x004f) {
2130 + printk(KERN_ERR "vesafb: Getting mode info block failed "
2131 + "(eax=0x%x)\n", (u32)tsk->regs.eax);
2132 + return -EINVAL;
2133 + }
2134 +
2135 + printk(KERN_INFO "vesafb: %s, %s, %s (OEM: %s)\n",
2136 + (char*)vbe_ib.oem_vendor_name_ptr,
2137 + (char*)vbe_ib.oem_product_name_ptr,
2138 + (char*)vbe_ib.oem_product_rev_ptr,
2139 + (char*)vbe_ib.oem_string_ptr);
2140 +
2141 + printk(KERN_INFO "vesafb: VBE version: %d.%d\n",
2142 + ((vbe_ib.vbe_version & 0xff00) >> 8),
2143 + vbe_ib.vbe_version & 0xff);
2144 + return 0;
2145 +}
2146 +
2147 +static int __init inline vesafb_vbe_getmodes(struct vesafb_task *tsk)
2148 +{
2149 + u16 *mode = 0;
2150 + int off = 0;
2151 +
2152 + /* Count available modes. */
2153 + mode = (u16*)vbe_ib.mode_list_ptr;
2154 + while (*mode != 0xffff) {
2155 + vbe_modes_cnt++;
2156 + mode++;
2157 + }
2158 +
2159 + vbe_modes = kmalloc(sizeof(struct vesafb_mode_ib)*
2160 + vbe_modes_cnt, GFP_KERNEL);
2161 + if (!vbe_modes)
2162 + return -ENOMEM;
2163 +
2164 + /* Get mode info for all available modes. */
2165 + mode = (u16*)vbe_ib.mode_list_ptr;
2166 +
2167 + while (*mode != 0xffff) {
2168 + struct vesafb_mode_ib *mib;
2169 +
2170 + vesafb_reset_task(tsk);
2171 + tsk->regs.eax = 0x4f01;
2172 + tsk->regs.ecx = (u32) *mode;
2173 + tsk->flags = TF_CALL | TF_RETURN_BUF | TF_BUF_DI;
2174 + tsk->buf = vbe_modes+off;
2175 + tsk->buf_len = sizeof(struct vesafb_mode_ib);
2176 + if (vesafb_queue_task(tsk))
2177 + return -EINVAL;
2178 + vesafb_wait_for_task(tsk);
2179 + mib = p_mode(tsk->buf);
2180 + mib->mode_id = *mode;
2181 +
2182 + /* We only want modes that are supported with the currennt
2183 + * hardware configuration (D0), color (D3), graphics (D4)
2184 + * and that have support for the LFB (D7). */
2185 + if ((mib->mode_attr & 0x99) == 0x99 &&
2186 + mib->bits_per_pixel >= 8) {
2187 + off++;
2188 + } else {
2189 + vbe_modes_cnt--;
2190 + }
2191 + mode++;
2192 + mib->depth = mib->red_len + mib->green_len + mib->blue_len;
2193 + /* Handle 8bpp modes and modes with broken color component
2194 + * lengths. */
2195 + if (mib->depth == 0 ||
2196 + (mib->depth == 24 && mib->bits_per_pixel == 32))
2197 + mib->depth = mib->bits_per_pixel;
2198 + }
2199 +
2200 + return 0;
2201 +}
2202 +
2203 +static int __init inline vesafb_vbe_getpmi(struct vesafb_task *tsk)
2204 +{
2205 + int i;
2206 +
2207 + vesafb_reset_task(tsk);
2208 + tsk->regs.eax = 0x4f0a;
2209 + tsk->regs.ebx = 0x0;
2210 + tsk->flags = TF_CALL;
2211 + if (vesafb_queue_task(tsk))
2212 + return -EINVAL;
2213 + vesafb_wait_for_task(tsk);
2214 +
2215 + if ((tsk->regs.eax & 0xffff) != 0x004f || tsk->regs.es < 0xc000) {
2216 + pmi_setpal = ypan = 0;
2217 + } else {
2218 + pmi_base = (u16*)phys_to_virt(((u32)tsk->regs.es << 4) +
2219 + tsk->regs.edi);
2220 + pmi_start = (void*)((char*)pmi_base + pmi_base[1]);
2221 + pmi_pal = (void*)((char*)pmi_base + pmi_base[2]);
2222 + printk(KERN_INFO "vesafb: protected mode interface info at "
2223 + "%04x:%04x\n",
2224 + (u16)tsk->regs.es, (u16)tsk->regs.edi);
2225 + printk(KERN_INFO "vesafb: pmi: set display start = %p, "
2226 + "set palette = %p\n", pmi_start, pmi_pal);
2227 +
2228 + if (pmi_base[3]) {
2229 + printk(KERN_INFO "vesafb: pmi: ports = ");
2230 + for (i = pmi_base[3]/2; pmi_base[i] != 0xffff; i++)
2231 + printk("%x ",pmi_base[i]);
2232 + printk("\n");
2233 +
2234 + /*
2235 + * memory areas not supported (yet?)
2236 + *
2237 + * Rules are: we have to set up a descriptor for the
2238 + * requested memory area and pass it in the ES register
2239 + * to the BIOS function.
2240 + */
2241 + if (pmi_base[i] != 0xffff) {
2242 + printk(KERN_INFO "vesafb: can't handle memory "
2243 + "requests, pmi disabled\n");
2244 + ypan = pmi_setpal = 0;
2245 + }
2246 + }
2247 + }
2248 + return 0;
2249 +}
2250 +
2251 +static int __init inline vesafb_vbe_getedid(struct vesafb_task *tsk,
2252 + struct fb_info *info)
2253 +{
2254 + int res = 0;
2255 +
2256 + if (noedid || vbe_ib.vbe_version < 0x0300)
2257 + return -EINVAL;
2258 +
2259 + vesafb_reset_task(tsk);
2260 + tsk->regs.eax = 0x4f15;
2261 + tsk->regs.ebx = 0;
2262 + tsk->regs.ecx = 0;
2263 + if (vesafb_queue_task(tsk))
2264 + return -EINVAL;
2265 + vesafb_wait_for_task(tsk);
2266 +
2267 + if ((tsk->regs.eax & 0xffff) != 0x004f)
2268 + return -EINVAL;
2269 +
2270 + if ((tsk->regs.ebx & 0x3) == 3) {
2271 + printk(KERN_INFO "vesafb: VBIOS/hardware supports both "
2272 + "DDC1 and DDC2 transfers\n");
2273 + } else if ((tsk->regs.ebx & 0x3) == 2) {
2274 + printk(KERN_INFO "vesafb: VBIOS/hardware supports DDC2 "
2275 + "transfers\n");
2276 + } else if ((tsk->regs.ebx & 0x3) == 1) {
2277 + printk(KERN_INFO "vesafb: VBIOS/hardware supports DDC1 "
2278 + "transfers\n");
2279 + } else {
2280 + printk(KERN_INFO "vesafb: VBIOS/hardware doesn't support "
2281 + "DDC transfers\n");
2282 + return -EINVAL;
2283 + }
2284 +
2285 + vesafb_reset_task(tsk);
2286 + tsk->regs.eax = 0x4f15;
2287 + tsk->regs.ebx = 1;
2288 + tsk->regs.ecx = tsk->regs.edx = 0;
2289 + tsk->flags = TF_CALL | TF_RETURN_BUF | TF_BUF_DI;
2290 + tsk->buf = kmalloc(EDID_LENGTH, GFP_KERNEL);
2291 + tsk->buf_len = EDID_LENGTH;
2292 +
2293 + if (vesafb_queue_task(tsk)) {
2294 + res = -EINVAL;
2295 + goto out;
2296 + }
2297 + vesafb_wait_for_task(tsk);
2298 +
2299 + if ((tsk->regs.eax & 0xffff) == 0x004f) {
2300 + fb_edid_to_monspecs(tsk->buf, &info->monspecs);
2301 + fb_videomode_to_modelist(info->monspecs.modedb,
2302 + info->monspecs.modedb_len, &info->modelist);
2303 + if (info->monspecs.vfmax && info->monspecs.hfmax) {
2304 + /* If the maximum pixel clock wasn't specified in
2305 + * the EDID block, set it to 300 MHz. */
2306 + if (info->monspecs.dclkmax == 0)
2307 + info->monspecs.dclkmax = 300 * 1000000;
2308 + info->monspecs.gtf = 1;
2309 + } else {
2310 + res = -EINVAL;
2311 + }
2312 + }
2313 +
2314 +out: kfree(tsk->buf);
2315 + return res;
2316 +}
2317 +
2318 +static void __init inline vesafb_vbe_getmonspecs(struct vesafb_task *tsk,
2319 + struct fb_info *info)
2320 +{
2321 + struct fb_var_screeninfo var;
2322 + int i;
2323 + memset(&info->monspecs, 0, sizeof(struct fb_monspecs));
2324 +
2325 + /* If we didn't get all necessary data from the EDID block,
2326 + * mark it as incompatible with the GTF. */
2327 + if (vesafb_vbe_getedid(tsk, info))
2328 + info->monspecs.gtf = 0;
2329 +
2330 + /* Kernel command line overrides. */
2331 + if (maxclk)
2332 + info->monspecs.dclkmax = maxclk * 1000000;
2333 + if (maxvf)
2334 + info->monspecs.vfmax = maxvf;
2335 + if (maxhf)
2336 + info->monspecs.hfmax = maxhf * 1000;
2337 +
2338 + /* In case DDC transfers are not supported the user can provide
2339 + * monitor limits manually. Lower limits are set to "safe" values. */
2340 + if (info->monspecs.gtf == 0 && maxclk && maxvf && maxhf) {
2341 + info->monspecs.dclkmin = 0;
2342 + info->monspecs.vfmin = 60;
2343 + info->monspecs.hfmin = 29000;
2344 + info->monspecs.gtf = 1;
2345 + }
2346 +
2347 + if (info->monspecs.gtf) {
2348 + printk(KERN_INFO
2349 + "vesafb: monitor limits: vf = %d Hz, hf = %d kHz, "
2350 + "clk = %d MHz\n", info->monspecs.vfmax,
2351 + (int)(info->monspecs.hfmax / 1000),
2352 + (int)(info->monspecs.dclkmax / 1000000));
2353 + /* Add valid VESA video modes to our modelist. */
2354 + for (i = 0; i < VESA_MODEDB_SIZE; i++) {
2355 + fb_videomode_to_var(&var, (struct fb_videomode *)
2356 + &vesa_modes[i]);
2357 + if (!fb_validate_mode(&var, info))
2358 + fb_add_videomode((struct fb_videomode *)
2359 + &vesa_modes[i],
2360 + &info->modelist);
2361 + }
2362 + } else {
2363 + /* Add all VESA video modes to our modelist. */
2364 + fb_videomode_to_modelist((struct fb_videomode *)vesa_modes,
2365 + VESA_MODEDB_SIZE, &info->modelist);
2366 + printk(KERN_INFO "vesafb: no monitor limits have been set\n");
2367 + }
2368 + return;
2369 +}
2370 +
2371 +static int __init inline vesafb_vbe_init(struct fb_info *info)
2372 +{
2373 + struct vesafb_task *tsk;
2374 + int res = 0;
2375 +
2376 + vesafb_create_task(tsk);
2377 + if (!tsk)
2378 + return -EINVAL;
2379 + if ((res = vesafb_vbe_getinfo(tsk)) != 0)
2380 + goto out;
2381 + if ((res = vesafb_vbe_getmodes(tsk)) != 0)
2382 + goto out;
2383 + if (pmi_setpal || ypan)
2384 + vesafb_vbe_getpmi(tsk);
2385 +
2386 + INIT_LIST_HEAD(&info->modelist);
2387 + vesafb_vbe_getmonspecs(tsk, info);
2388 +
2389 +out: kfree(tsk);
2390 + return res;
2391 +}
2392 +
2393 +static int __init decode_mode(u32 *xres, u32 *yres, u32 *bpp, u32 *refresh)
2394 +{
2395 + int len = strlen(mode_option), i, err = 0;
2396 + u8 res_specified = 0, bpp_specified = 0, refresh_specified = 0,
2397 + yres_specified = 0;
2398 +
2399 + for (i = len-1; i >= 0; i--) {
2400 + switch (mode_option[i]) {
2401 + case '@':
2402 + len = i;
2403 + if (!refresh_specified && !bpp_specified &&
2404 + !yres_specified) {
2405 + *refresh = simple_strtoul(&mode_option[i+1],
2406 + NULL, 0);
2407 + refresh_specified = 1;
2408 + } else
2409 + goto out;
2410 + break;
2411 + case '-':
2412 + len = i;
2413 + if (!bpp_specified && !yres_specified) {
2414 + *bpp = simple_strtoul(&mode_option[i+1],
2415 + NULL, 0);
2416 + bpp_specified = 1;
2417 + } else
2418 + goto out;
2419 + break;
2420 + case 'x':
2421 + if (!yres_specified) {
2422 + *yres = simple_strtoul(&mode_option[i+1],
2423 + NULL, 0);
2424 + yres_specified = 1;
2425 + } else
2426 + goto out;
2427 + break;
2428 + case '0'...'9':
2429 + break;
2430 + default:
2431 + goto out;
2432 + }
2433 + }
2434 +
2435 + if (i < 0 && yres_specified) {
2436 + *xres = simple_strtoul(mode_option, NULL, 0);
2437 + res_specified = 1;
2438 + }
2439 +
2440 +out: if (!res_specified || !yres_specified) {
2441 + printk(KERN_ERR "vesafb: invalid resolution, "
2442 + "%s not specified\n",
2443 + (!res_specified) ? "width" : "height");
2444 + err = -EINVAL;
2445 + }
2446 +
2447 + return err;
2448 +}
2449 +
2450 +static int __init vesafb_init_set_mode(struct fb_info *info)
2451 +{
2452 + struct fb_videomode *fbmode;
2453 + struct fb_videomode mode;
2454 + int i, modeid, refresh = 0;
2455 + u8 refresh_specified = 0;
2456 +
2457 + if (!mode_option)
2458 + mode_option = CONFIG_FB_VESA_DEFAULT_MODE;
2459 +
2460 + if (vbemode > 0) {
2461 + for (i = 0; i < vbe_modes_cnt; i++) {
2462 + if (vbe_modes[i].mode_id == vbemode) {
2463 + info->var.vmode = FB_VMODE_NONINTERLACED;
2464 + info->var.sync = FB_SYNC_VERT_HIGH_ACT;
2465 + vesafb_setup_var(&info->var, info,
2466 + &vbe_modes[i]);
2467 + fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON,
2468 + 60, &info->var, info);
2469 + /* With pixclock set to 0, the default BIOS
2470 + * timings will be used in set_par(). */
2471 + info->var.pixclock = 0;
2472 + modeid = i;
2473 + goto out;
2474 + }
2475 + }
2476 + printk(KERN_INFO "specified VBE mode %d not found\n",
2477 + vbemode);
2478 + vbemode = 0;
2479 + }
2480 +
2481 + /* Decode the mode specified on the kernel command line. We save
2482 + * the depth into bits_per_pixel, which is wrong, but will work
2483 + * anyway. */
2484 + if (decode_mode(&info->var.xres, &info->var.yres,
2485 + &info->var.bits_per_pixel, &refresh))
2486 + return -EINVAL;
2487 + if (refresh)
2488 + refresh_specified = 1;
2489 + else
2490 + refresh = 60;
2491 +
2492 + /* Look for a matching VBE mode. We can live if an exact match
2493 + * cannot be found. */
2494 + modeid = vesafb_find_vbe_mode(info->var.xres, info->var.yres,
2495 + info->var.bits_per_pixel, 0);
2496 +
2497 + if (modeid == -1) {
2498 + return -EINVAL;
2499 + } else {
2500 + info->var.vmode = FB_VMODE_NONINTERLACED;
2501 + info->var.sync = FB_SYNC_VERT_HIGH_ACT;
2502 + vesafb_setup_var(&info->var, info, &vbe_modes[modeid]);
2503 + }
2504 + if (vbe_ib.vbe_version < 0x0300) {
2505 + fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60,
2506 + &info->var, info);
2507 + goto out;
2508 + }
2509 + if (!gtf) {
2510 + struct fb_videomode tmode;
2511 +
2512 + if (refresh_specified) {
2513 + fb_var_to_videomode(&tmode, &info->var);
2514 + tmode.refresh = refresh;
2515 + fbmode = fb_find_nearest_mode(&tmode,
2516 + &info->modelist);
2517 + } else
2518 + fbmode = fb_find_best_mode(&info->var,
2519 + &info->modelist);
2520 +
2521 + if (fbmode->xres == info->var.xres &&
2522 + fbmode->yres == info->var.yres &&
2523 + !(fbmode->vmode & (FB_VMODE_INTERLACED | FB_VMODE_DOUBLE))
2524 + && (!refresh_specified ||
2525 + abs(refresh - fbmode->refresh) <= 5)) {
2526 + fb_videomode_to_var(&info->var, fbmode);
2527 + return modeid;
2528 + }
2529 + }
2530 + i = FB_MAXTIMINGS;
2531 + if (!info->monspecs.gtf)
2532 + i = FB_IGNOREMON | FB_VSYNCTIMINGS;
2533 + else if (refresh_specified)
2534 + i = FB_VSYNCTIMINGS;
2535 + if (!fb_get_mode(i, refresh, &info->var, info))
2536 + goto out;
2537 + if (info->monspecs.gtf &&
2538 + !fb_get_mode(FB_MAXTIMINGS, 0, &info->var, info))
2539 + goto out;
2540 + /* Use default refresh rate */
2541 + printk(KERN_WARNING "vesafb: using default BIOS refresh rate\n");
2542 + info->var.pixclock = 0;
2543 +
2544 +out:
2545 + fb_var_to_videomode(&mode, &info->var);
2546 + fb_add_videomode(&mode, &info->modelist);
2547 + return modeid;
2548 +}
2549 +
2550 +static int __init vesafb_probe(struct platform_device *dev)
2551 +{
2552 + char entry[16];
2553 + struct fb_info *info;
2554 + struct vesafb_mode_ib *mode = NULL;
2555 + int err = 0, i, h;
2556 + unsigned int size_vmode;
2557 + unsigned int size_remap;
2558 + unsigned int size_total;
2559 +
2560 + vesafb_info = info = framebuffer_alloc(sizeof(struct vesafb_par) +
2561 + sizeof(u32) * 256, &dev->dev);
2562 + if (!info)
2563 + return -ENOMEM;
2564 +
2565 + if (vesafb_wait_for_thread()) {
2566 + printk(KERN_ERR "vesafb: vesafb thread not running\n");
2567 + framebuffer_release(info);
2568 + return -EINVAL;
2569 + }
2570 +
2571 + if (vesafb_vbe_init(info)) {
2572 + printk(KERN_ERR "vesafb: vbe_init failed\n");
2573 + err = -EINVAL;
2574 + goto out;
2575 + }
2576 +
2577 + vesafb_fix.ypanstep = ypan ? 1 : 0;
2578 + vesafb_fix.ywrapstep = (ypan>1) ? 1 : 0;
2579 +
2580 + info->pseudo_palette = ((u8*)info->par + sizeof(struct vesafb_par));
2581 + info->fbops = &vesafb_ops;
2582 + info->var = vesafb_defined;
2583 + info->fix = vesafb_fix;
2584 +
2585 + if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
2586 + err = -ENXIO;
2587 + goto out;
2588 + }
2589 +
2590 + i = vesafb_init_set_mode(info);
2591 + if (i < 0) {
2592 + err = -EINVAL;
2593 + goto out_cmap;
2594 + } else
2595 + mode = &vbe_modes[i];
2596 +
2597 + /* Disable blanking if the user requested so. */
2598 + if (!blank) {
2599 + info->fbops->fb_blank = NULL;
2600 + }
2601 +
2602 + /* Find out how much IO memory is required for the mode with
2603 + * the highest resolution. */
2604 + size_remap = 0;
2605 + for (i = 0; i < vbe_modes_cnt; i++) {
2606 + h = vbe_modes[i].bytes_per_scan_line * vbe_modes[i].y_res;
2607 + if (h > size_remap)
2608 + size_remap = h;
2609 + }
2610 + size_remap *= 2;
2611 +
2612 + /* size_vmode -- that is the amount of memory needed for the
2613 + * used video mode, i.e. the minimum amount of
2614 + * memory we need. */
2615 + if (mode != NULL) {
2616 + size_vmode = info->var.yres * mode->bytes_per_scan_line;
2617 + } else {
2618 + size_vmode = info->var.yres * info->var.xres *
2619 + ((info->var.bits_per_pixel + 7) >> 3);
2620 + }
2621 +
2622 + /* size_total -- all video memory we have. Used for mtrr
2623 + * entries, ressource allocation and bounds
2624 + * checking. */
2625 + size_total = vbe_ib.total_memory * 65536;
2626 + if (vram_total)
2627 + size_total = vram_total * 1024 * 1024;
2628 + if (size_total < size_vmode)
2629 + size_total = size_vmode;
2630 + ((struct vesafb_par*)(info->par))->mem_total = size_total;
2631 +
2632 + /* size_remap -- the amount of video memory we are going to
2633 + * use for vesafb. With modern cards it is no
2634 + * option to simply use size_total as th
2635 + * wastes plenty of kernel address space. */
2636 + if (vram_remap)
2637 + size_remap = vram_remap * 1024 * 1024;
2638 + if (size_remap < size_vmode)
2639 + size_remap = size_vmode;
2640 + if (size_remap > size_total)
2641 + size_remap = size_total;
2642 +
2643 + info->fix.smem_len = size_remap;
2644 + info->fix.smem_start = mode->phys_base_ptr;
2645 +
2646 + /* We have to set it here, because when setup_var() was called,
2647 + * smem_len wasn't defined yet. */
2648 + info->var.yres_virtual = info->fix.smem_len /
2649 + mode->bytes_per_scan_line;
2650 +
2651 + if (ypan && info->var.yres_virtual > info->var.yres) {
2652 + printk(KERN_INFO "vesafb: scrolling: %s "
2653 + "using protected mode interface, "
2654 + "yres_virtual=%d\n",
2655 + (ypan > 1) ? "ywrap" : "ypan",info->var.yres_virtual);
2656 + } else {
2657 + printk(KERN_INFO "vesafb: scrolling: redraw\n");
2658 + info->var.yres_virtual = info->var.yres;
2659 + ypan = 0;
2660 + }
2661 +
2662 + info->flags = FBINFO_FLAG_DEFAULT |
2663 + (ypan) ? FBINFO_HWACCEL_YPAN : 0;
2664 +
2665 + if (!ypan)
2666 + info->fbops->fb_pan_display = NULL;
2667 +
2668 + if (!request_mem_region(info->fix.smem_start, size_total, "vesafb")) {
2669 + printk(KERN_WARNING "vesafb: cannot reserve video memory at "
2670 + "0x%lx\n", info->fix.smem_start);
2671 + /* We cannot make this fatal. Sometimes this comes from magic
2672 + spaces our resource handlers simply don't know about. */
2673 + }
2674 +
2675 + info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
2676 +
2677 + if (!info->screen_base) {
2678 + printk(KERN_ERR
2679 + "vesafb: abort, cannot ioremap video memory "
2680 + "0x%x @ 0x%lx\n",
2681 + info->fix.smem_len, info->fix.smem_start);
2682 + err = -EIO;
2683 + goto out_mem;
2684 + }
2685 +
2686 + /* Request failure does not faze us, as vgacon probably has this
2687 + region already (FIXME) */
2688 + request_region(0x3c0, 32, "vesafb");
2689 +
2690 +#ifdef CONFIG_MTRR
2691 + if (mtrr && !(info->fix.smem_start & (PAGE_SIZE - 1))) {
2692 + int temp_size = size_total;
2693 + unsigned int type = 0;
2694 +
2695 + switch (mtrr) {
2696 + case 1:
2697 + type = MTRR_TYPE_UNCACHABLE;
2698 + break;
2699 + case 2:
2700 + type = MTRR_TYPE_WRBACK;
2701 + break;
2702 + case 3:
2703 + type = MTRR_TYPE_WRCOMB;
2704 + break;
2705 + case 4:
2706 + type = MTRR_TYPE_WRTHROUGH;
2707 + break;
2708 + default:
2709 + type = 0;
2710 + break;
2711 + }
2712 +
2713 + if (type) {
2714 + int rc;
2715 +
2716 + /* Find the largest power-of-two */
2717 + while (temp_size & (temp_size - 1))
2718 + temp_size &= (temp_size - 1);
2719 +
2720 + /* Try and find a power of two to add */
2721 + do {
2722 + rc = mtrr_add(info->fix.smem_start,
2723 + temp_size, type, 1);
2724 + temp_size >>= 1;
2725 + } while (temp_size >= PAGE_SIZE && rc == -EINVAL);
2726 + }
2727 + }
2728 +#endif /* CONFIG_MTRR */
2729 +
2730 + if (register_framebuffer(info) < 0) {
2731 + printk(KERN_ERR
2732 + "vesafb: failed to register framebuffer device\n");
2733 + err = -EINVAL;
2734 + goto out_mem;
2735 + }
2736 +
2737 + printk(KERN_INFO "vesafb: framebuffer at 0x%lx, mapped to 0x%p, "
2738 + "using %dk, total %dk\n", info->fix.smem_start,
2739 + info->screen_base, size_remap/1024, size_total/1024);
2740 + printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
2741 + info->fix.id);
2742 +
2743 + sprintf(entry, "fb%d", info->node);
2744 + proc_mkdir(entry, 0);
2745 +
2746 + sprintf(entry, "fb%d/modes", info->node);
2747 + create_proc_read_entry(entry, 0, 0, vesafb_read_proc_modes, NULL);
2748 +
2749 + sprintf(entry, "fb%d/vbe_info", info->node);
2750 + create_proc_read_entry(entry, 0, 0, vesafb_read_proc_vbe_info, NULL);
2751 + return 0;
2752 +
2753 +out_mem:
2754 + release_mem_region(info->fix.smem_start, size_total);
2755 + if (!list_empty(&info->modelist))
2756 + fb_destroy_modelist(&info->modelist);
2757 + fb_destroy_modedb(info->monspecs.modedb);
2758 +out_cmap:
2759 + fb_dealloc_cmap(&info->cmap);
2760 +out:
2761 + framebuffer_release(info);
2762 + vesafb_info = NULL;
2763 + kfree(vbe_modes);
2764 + vbe_modes = NULL;
2765 + return err;
2766 +}
2767 +
2768 +int __init vesafb_init(void)
2769 +{
2770 + int ret;
2771 +#ifndef MODULE
2772 + char *option = NULL;
2773 +
2774 + if (fb_get_options("vesafb", &option))
2775 + return -ENODEV;
2776 + vesafb_setup(option);
2777 +#endif
2778 + ret = platform_driver_register(&vesafb_driver);
2779 +
2780 + if (!ret) {
2781 + vesafb_device = platform_device_alloc("vesafb", 0);
2782 +
2783 + if (vesafb_device)
2784 + ret = platform_device_add(vesafb_device);
2785 + else
2786 + ret = -ENOMEM;
2787 +
2788 + if (ret) {
2789 + platform_device_put(vesafb_device);
2790 + platform_driver_unregister(&vesafb_driver);
2791 + }
2792 + }
2793 + return ret;
2794 +}
2795 +
2796 +module_init(vesafb_init);
2797 +
2798 +#ifdef MODULE
2799 +void __exit vesafb_exit(void)
2800 +{
2801 + char entry[16];
2802 +
2803 + if (vesafb_info)
2804 + unregister_framebuffer(vesafb_info);
2805 +
2806 + platform_device_unregister(vesafb_device);
2807 + platform_driver_unregister(&vesafb_driver);
2808 +
2809 + if (vesafb_info) {
2810 + struct vesafb_par *par = (struct vesafb_par*)vesafb_info->par;
2811 +
2812 + sprintf(entry, "fb%d/modes", vesafb_info->node);
2813 + remove_proc_entry(entry, NULL);
2814 +
2815 + sprintf(entry, "fb%d/vbe_info", vesafb_info->node);
2816 + remove_proc_entry(entry, NULL);
2817 +
2818 + sprintf(entry, "fb%d", vesafb_info->node);
2819 + remove_proc_entry(entry, NULL);
2820 +
2821 + iounmap(vesafb_info->screen_base);
2822 + release_mem_region(vesafb_info->fix.smem_start,
2823 + par->mem_total);
2824 + fb_dealloc_cmap(&vesafb_info->cmap);
2825 + if (!list_empty(&vesafb_info->modelist))
2826 + fb_destroy_modelist(&vesafb_info->modelist);
2827 + fb_destroy_modedb(vesafb_info->monspecs.modedb);
2828 + framebuffer_release(vesafb_info);
2829 + }
2830 +
2831 + if (vbe_modes != NULL)
2832 + kfree(vbe_modes);
2833 +}
2834 +
2835 +module_exit(vesafb_exit);
2836 +
2837 +static inline int param_get_scroll(char *buffer, struct kernel_param *kp)
2838 +{
2839 + return 0;
2840 +}
2841 +static inline int param_set_scroll(const char *val, struct kernel_param *kp)
2842 +{
2843 + ypan = 0;
2844 +
2845 + if (! strcmp(val, "redraw"))
2846 + ypan = 0;
2847 + else if (! strcmp(val, "ypan"))
2848 + ypan = 1;
2849 + else if (! strcmp(val, "ywrap"))
2850 + ypan = 2;
2851 +
2852 + return 0;
2853 +}
2854 +
2855 +#define param_check_scroll(name, p) __param_check(name, p, void);
2856 +
2857 +module_param_named(scroll, ypan, scroll, 0);
2858 +MODULE_PARM_DESC(scroll,"Scrolling mode, set to 'redraw', 'ypan' or 'ywrap'");
2859 +module_param_named(vgapal, pmi_setpal, invbool, 0);
2860 +MODULE_PARM_DESC(vgapal,"bool: set palette using VGA registers");
2861 +module_param_named(pmipal, pmi_setpal, bool, 0);
2862 +MODULE_PARM_DESC(pmipal,"bool: set palette using PMI calls");
2863 +module_param(mtrr, uint, 0);
2864 +MODULE_PARM_DESC(mtrr,"Memory Type Range Registers setting. Use 0 to disable.");
2865 +module_param(blank, bool, 1);
2866 +MODULE_PARM_DESC(blank,"bool: enable hardware blanking");
2867 +module_param(nocrtc, bool, 0);
2868 +MODULE_PARM_DESC(nocrtc,"bool: ignore CRTC timings when setting modes");
2869 +module_param(noedid, bool, 0);
2870 +MODULE_PARM_DESC(noedid,"bool: ignore EDID-provided monitor limits "
2871 + "when setting modes");
2872 +module_param(gtf, bool, 0);
2873 +MODULE_PARM_DESC(gtf,"bool: force use of VESA GTF to calculate mode timings");
2874 +module_param(vram_remap, uint, 0);
2875 +MODULE_PARM_DESC(vram_remap,"Set amount of video memory to be used [MiB]");
2876 +module_param(vram_total, uint, 0);
2877 +MODULE_PARM_DESC(vram_total,"Set total amount of video memoery [MiB]");
2878 +module_param(maxclk, ushort, 0);
2879 +MODULE_PARM_DESC(maxclk,"Maximum pixelclock [MHz], overrides EDID data");
2880 +module_param(maxhf, ushort, 0);
2881 +MODULE_PARM_DESC(maxhf,"Maximum horizontal frequency [kHz], "
2882 + "overrides EDID data");
2883 +module_param(maxvf, ushort, 0);
2884 +MODULE_PARM_DESC(maxvf,"Maximum vertical frequency [Hz], "
2885 + "overrides EDID data");
2886 +module_param_named(mode, mode_option, charp, 0);
2887 +MODULE_PARM_DESC(mode, "Specify resolution as "
2888 + "\"<xres>x<yres>[-<bpp>][@<refresh>]\"");
2889 +module_param(vbemode, ushort, 0);
2890 +MODULE_PARM_DESC(vbemode,"VBE mode number to set, overrides 'mode' setting");
2891 +
2892 +#endif /* MODULE */
2893 +
2894 +MODULE_LICENSE("GPL");
2895 +MODULE_AUTHOR("Michal Januszewski");
2896 +MODULE_DESCRIPTION("Framebuffer driver for VBE2.0+ compliant graphics boards");
2897 +
2898 Index: linux-git/include/linux/sched.h
2899 ===================================================================
2900 --- linux-git.orig/include/linux/sched.h
2901 +++ linux-git/include/linux/sched.h
2902 @@ -1390,6 +1390,8 @@ extern void mmput(struct mm_struct *);
2903 extern struct mm_struct *get_task_mm(struct task_struct *task);
2904 /* Remove the current tasks stale references to the old mm_struct */
2905 extern void mm_release(struct task_struct *, struct mm_struct *);
2906 +/* Create a new mm for a kernel thread */
2907 +extern int set_new_mm(void);
2908
2909 extern int copy_thread(int, unsigned long, unsigned long, unsigned long, struct task_struct *, struct pt_regs *);
2910 extern void flush_thread(void);
2911 Index: linux-git/include/video/vesa.h
2912 ===================================================================
2913 --- /dev/null
2914 +++ linux-git/include/video/vesa.h
2915 @@ -0,0 +1,150 @@
2916 +#if 0
2917 +#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , \
2918 + ## args)
2919 +#else
2920 +#define DPRINTK(fmt, args...)
2921 +#endif
2922 +
2923 +#define p_crtc(arg) ((struct vesafb_crtc_ib*)(arg))
2924 +#define p_vbe(arg) ((struct vesafb_vbe_ib*)(arg))
2925 +#define p_mode(arg) ((struct vesafb_mode_ib*)(arg))
2926 +
2927 +struct vesafb_task {
2928 + u8 flags;
2929 + void *buf;
2930 + int buf_len;
2931 + struct vm86_regs regs;
2932 + struct list_head node;
2933 + struct completion done;
2934 +};
2935 +
2936 +/* Vesafb task flags and masks */
2937 +#define TF_CALL 0x00
2938 +#define TF_EXIT 0x01
2939 +#define TF_GETVBEIB 0x02
2940 +#define TF_BUF_DI 0x04
2941 +#define TF_BUF_BX 0x08
2942 +#define TF_RETURN_BUF 0x10
2943 +
2944 +/* Macros and functions for manipulating vesafb tasks */
2945 +#define vesafb_create_task(task) \
2946 +do { \
2947 + task = kmalloc(sizeof(struct vesafb_task), GFP_ATOMIC); \
2948 + if (task) \
2949 + memset(task, 0, sizeof(struct vesafb_task)); \
2950 + init_completion(&task->done); \
2951 +} while (0)
2952 +
2953 +#define vesafb_wait_for_task(task) wait_for_completion(&task->done);
2954 +#define vesafb_reset_task(task) init_completion(&task->done);
2955 +int vesafb_queue_task(struct vesafb_task *task);
2956 +
2957 +/* Functions for controlling the vesafb thread */
2958 +int vesafb_wait_for_thread(void);
2959 +
2960 +#define VBE_CAP_CAN_SWITCH_DAC 0x01
2961 +#define VBE_CAP_VGACOMPAT 0x02
2962 +
2963 +/* This struct is 512 bytes long */
2964 +struct vesafb_vbe_ib {
2965 + char vbe_signature[4];
2966 + u16 vbe_version;
2967 + u32 oem_string_ptr;
2968 + u32 capabilities;
2969 + u32 mode_list_ptr;
2970 + u16 total_memory;
2971 + u16 oem_software_rev;
2972 + u32 oem_vendor_name_ptr;
2973 + u32 oem_product_name_ptr;
2974 + u32 oem_product_rev_ptr;
2975 + u8 reserved[222];
2976 + char oem_data[256];
2977 +} __attribute__ ((packed));
2978 +
2979 +struct vesafb_crtc_ib {
2980 + u16 horiz_total;
2981 + u16 horiz_start;
2982 + u16 horiz_end;
2983 + u16 vert_total;
2984 + u16 vert_start;
2985 + u16 vert_end;
2986 + u8 flags;
2987 + u32 pixel_clock;
2988 + u16 refresh_rate;
2989 + u8 reserved[40];
2990 +} __attribute__ ((packed));
2991 +
2992 +#define VBE_MODE_VGACOMPAT 0x20
2993 +
2994 +struct vesafb_mode_ib {
2995 + /* for all VBE revisions */
2996 + u16 mode_attr;
2997 + u8 winA_attr;
2998 + u8 winB_attr;
2999 + u16 win_granularity;
3000 + u16 win_size;
3001 + u16 winA_seg;
3002 + u16 winB_seg;
3003 + u32 win_func_ptr;
3004 + u16 bytes_per_scan_line;
3005 +
3006 + /* for VBE 1.2+ */
3007 + u16 x_res;
3008 + u16 y_res;
3009 + u8 x_char_size;
3010 + u8 y_char_size;
3011 + u8 planes;
3012 + u8 bits_per_pixel;
3013 + u8 banks;
3014 + u8 memory_model;
3015 + u8 bank_size;
3016 + u8 image_pages;
3017 + u8 reserved1;
3018 +
3019 + /* Direct color fields for direct/6 and YUV/7 memory models. */
3020 + /* Offsets are bit positions of lsb in the mask. */
3021 + u8 red_len;
3022 + u8 red_off;
3023 + u8 green_len;
3024 + u8 green_off;
3025 + u8 blue_len;
3026 + u8 blue_off;
3027 + u8 rsvd_len;
3028 + u8 rsvd_off;
3029 + u8 direct_color_info; /* direct color mode attributes */
3030 +
3031 + /* for VBE 2.0+ */
3032 + u32 phys_base_ptr;
3033 + u8 reserved2[6];
3034 +
3035 + /* for VBE 3.0+ */
3036 + u16 lin_bytes_per_scan_line;
3037 + u8 bnk_image_pages;
3038 + u8 lin_image_pages;
3039 + u8 lin_red_len;
3040 + u8 lin_red_off;
3041 + u8 lin_green_len;
3042 + u8 lin_green_off;
3043 + u8 lin_blue_len;
3044 + u8 lin_blue_off;
3045 + u8 lin_rsvd_len;
3046 + u8 lin_rsvd_off;
3047 + u32 max_pixel_clock;
3048 + u16 mode_id;
3049 + u8 depth;
3050 +} __attribute__ ((packed));
3051 +
3052 +struct vesafb_pal_entry {
3053 + u_char blue, green, red, pad;
3054 +} __attribute__ ((packed));
3055 +
3056 +struct vesafb_par {
3057 + u8 *vbe_state;
3058 + int vbe_state_size;
3059 + atomic_t ref_count;
3060 +
3061 + u32 mem_total;
3062 + int mode_idx;
3063 + struct vesafb_crtc_ib crtc;
3064 +};
3065 +
3066 Index: linux-git/kernel/fork.c
3067 ===================================================================
3068 --- linux-git.orig/kernel/fork.c
3069 +++ linux-git/kernel/fork.c
3070 @@ -100,6 +100,7 @@ struct kmem_cache *fs_cachep;
3071
3072 /* SLAB cache for vm_area_struct structures */
3073 struct kmem_cache *vm_area_cachep;
3074 +EXPORT_SYMBOL_GPL(vm_area_cachep);
3075
3076 /* SLAB cache for mm_struct structures (tsk->mm) */
3077 static struct kmem_cache *mm_cachep;
3078 @@ -399,6 +400,40 @@ void mmput(struct mm_struct *mm)
3079 EXPORT_SYMBOL_GPL(mmput);
3080
3081 /**
3082 + * set_new_mm - allocate, init and activate a new mm for a kernel thread
3083 + */
3084 +int set_new_mm(void)
3085 +{
3086 + struct mm_struct *mm;
3087 + struct task_struct *tsk = current;
3088 + struct mm_struct *active_mm;
3089 +
3090 + mm = mm_alloc();
3091 + if (!mm)
3092 + goto fail_nomem;
3093 + if (init_new_context(current,mm))
3094 + goto fail_nocontext;
3095 +
3096 + task_lock(tsk);
3097 + tsk->flags |= PF_BORROWED_MM;
3098 + active_mm = tsk->active_mm;
3099 + current->mm = mm;
3100 + current->active_mm = mm;
3101 + activate_mm(active_mm, mm);
3102 + task_unlock(current);
3103 +
3104 + /* Drop the previous active_mm */
3105 + mmdrop(active_mm);
3106 + return 0;
3107 +
3108 +fail_nocontext:
3109 + mmdrop(mm);
3110 +fail_nomem:
3111 + return -EINVAL;
3112 +}
3113 +EXPORT_SYMBOL_GPL(set_new_mm);
3114 +
3115 +/**
3116 * get_task_mm - acquire a reference to the task's mm
3117 *
3118 * Returns %NULL if the task has no mm. Checks PF_BORROWED_MM (meaning
3119 Index: linux-git/mm/memory.c
3120 ===================================================================
3121 --- linux-git.orig/mm/memory.c
3122 +++ linux-git/mm/memory.c
3123 @@ -1193,6 +1193,7 @@ int zeromap_page_range(struct vm_area_st
3124 } while (pgd++, addr = next, addr != end);
3125 return err;
3126 }
3127 +EXPORT_SYMBOL_GPL(zeromap_page_range);
3128
3129 pte_t * fastcall get_locked_pte(struct mm_struct *mm, unsigned long addr, spinlock_t **ptl)
3130 {
3131 Index: linux-git/mm/mmap.c
3132 ===================================================================
3133 --- linux-git.orig/mm/mmap.c
3134 +++ linux-git/mm/mmap.c
3135 @@ -2031,6 +2031,7 @@ int insert_vm_struct(struct mm_struct *
3136 vma_link(mm, vma, prev, rb_link, rb_parent);
3137 return 0;
3138 }
3139 +EXPORT_SYMBOL_GPL(insert_vm_struct);
3140
3141 /*
3142 * Copy the vma structure to a new location in the same mm,

  ViewVC Help
Powered by ViewVC 1.1.20