aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/boot/video-mode.c
diff options
context:
space:
mode:
authorPavel Machek <pavel@suse.cz>2008-04-10 17:28:10 -0400
committerIngo Molnar <mingo@elte.hu>2008-04-17 11:41:37 -0400
commite44b7b7525ad9d43163ab5e60c784325419e0ea6 (patch)
treee2918917a97b4c9de4367e8778ed78afc762b9f8 /arch/x86/boot/video-mode.c
parentf49688d459c5eaa62db3597cbfd3cb13e361d415 (diff)
x86: move suspend wakeup code to C
Move wakeup code to .c, so that video mode setting code can be shared between boot and wakeup. Remove nasty assembly code in 64-bit case by re-using trampoline code. Stack setup was fixed to clear high 16bits of %esp, maybe that fixes some machines. .c code sharing and morse code was done H. Peter Anvin, Sam Ravnborg reviewed kbuild related stuff, and it seems okay to him. Rafael did some cleanups. [rjw: * Made the patch stop breaking compilation on x86-32 * Added arch/x86/kernel/acpi/sleep.h * Got rid of compiler warnings in arch/x86/kernel/acpi/sleep.c * Fixed 32-bit compilation on x86-64 systems * Added include/asm-x86/trampoline.h and fixed the non-SMP compilation on 64-bit x86 * Removed arch/x86/kernel/acpi/sleep_32.c which was not used * Fixed some breakage caused by the integration of smpboot.c done under us in the meantime] Signed-off-by: Pavel Machek <pavel@suse.cz> Signed-off-by: H. Peter Anvin <hpa@zytor.com> Reviewed-by: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/boot/video-mode.c')
-rw-r--r--arch/x86/boot/video-mode.c173
1 files changed, 173 insertions, 0 deletions
diff --git a/arch/x86/boot/video-mode.c b/arch/x86/boot/video-mode.c
new file mode 100644
index 000000000000..748e8d06290a
--- /dev/null
+++ b/arch/x86/boot/video-mode.c
@@ -0,0 +1,173 @@
1/* -*- linux-c -*- ------------------------------------------------------- *
2 *
3 * Copyright (C) 1991, 1992 Linus Torvalds
4 * Copyright 2007-2008 rPath, Inc. - All Rights Reserved
5 *
6 * This file is part of the Linux kernel, and is made available under
7 * the terms of the GNU General Public License version 2.
8 *
9 * ----------------------------------------------------------------------- */
10
11/*
12 * arch/i386/boot/video-mode.c
13 *
14 * Set the video mode. This is separated out into a different
15 * file in order to be shared with the ACPI wakeup code.
16 */
17
18#include "boot.h"
19#include "video.h"
20#include "vesa.h"
21
22/*
23 * Common variables
24 */
25int adapter; /* 0=CGA/MDA/HGC, 1=EGA, 2=VGA+ */
26u16 video_segment;
27int force_x, force_y; /* Don't query the BIOS for cols/rows */
28
29int do_restore; /* Screen contents changed during mode flip */
30int graphic_mode; /* Graphic mode with linear frame buffer */
31
32/* Probe the video drivers and have them generate their mode lists. */
33void probe_cards(int unsafe)
34{
35 struct card_info *card;
36 static u8 probed[2];
37
38 if (probed[unsafe])
39 return;
40
41 probed[unsafe] = 1;
42
43 for (card = video_cards; card < video_cards_end; card++) {
44 if (card->unsafe == unsafe) {
45 if (card->probe)
46 card->nmodes = card->probe();
47 else
48 card->nmodes = 0;
49 }
50 }
51}
52
53/* Test if a mode is defined */
54int mode_defined(u16 mode)
55{
56 struct card_info *card;
57 struct mode_info *mi;
58 int i;
59
60 for (card = video_cards; card < video_cards_end; card++) {
61 mi = card->modes;
62 for (i = 0; i < card->nmodes; i++, mi++) {
63 if (mi->mode == mode)
64 return 1;
65 }
66 }
67
68 return 0;
69}
70
71/* Set mode (without recalc) */
72static int raw_set_mode(u16 mode, u16 *real_mode)
73{
74 int nmode, i;
75 struct card_info *card;
76 struct mode_info *mi;
77
78 /* Drop the recalc bit if set */
79 mode &= ~VIDEO_RECALC;
80
81 /* Scan for mode based on fixed ID, position, or resolution */
82 nmode = 0;
83 for (card = video_cards; card < video_cards_end; card++) {
84 mi = card->modes;
85 for (i = 0; i < card->nmodes; i++, mi++) {
86 int visible = mi->x || mi->y;
87
88 if ((mode == nmode && visible) ||
89 mode == mi->mode ||
90 mode == (mi->y << 8)+mi->x) {
91 *real_mode = mi->mode;
92 return card->set_mode(mi);
93 }
94
95 if (visible)
96 nmode++;
97 }
98 }
99
100 /* Nothing found? Is it an "exceptional" (unprobed) mode? */
101 for (card = video_cards; card < video_cards_end; card++) {
102 if (mode >= card->xmode_first &&
103 mode < card->xmode_first+card->xmode_n) {
104 struct mode_info mix;
105 *real_mode = mix.mode = mode;
106 mix.x = mix.y = 0;
107 return card->set_mode(&mix);
108 }
109 }
110
111 /* Otherwise, failure... */
112 return -1;
113}
114
115/*
116 * Recalculate the vertical video cutoff (hack!)
117 */
118static void vga_recalc_vertical(void)
119{
120 unsigned int font_size, rows;
121 u16 crtc;
122 u8 pt, ov;
123
124 set_fs(0);
125 font_size = rdfs8(0x485); /* BIOS: font size (pixels) */
126 rows = force_y ? force_y : rdfs8(0x484)+1; /* Text rows */
127
128 rows *= font_size; /* Visible scan lines */
129 rows--; /* ... minus one */
130
131 crtc = vga_crtc();
132
133 pt = in_idx(crtc, 0x11);
134 pt &= ~0x80; /* Unlock CR0-7 */
135 out_idx(pt, crtc, 0x11);
136
137 out_idx((u8)rows, crtc, 0x12); /* Lower height register */
138
139 ov = in_idx(crtc, 0x07); /* Overflow register */
140 ov &= 0xbd;
141 ov |= (rows >> (8-1)) & 0x02;
142 ov |= (rows >> (9-6)) & 0x40;
143 out_idx(ov, crtc, 0x07);
144}
145
146/* Set mode (with recalc if specified) */
147int set_mode(u16 mode)
148{
149 int rv;
150 u16 real_mode;
151
152 /* Very special mode numbers... */
153 if (mode == VIDEO_CURRENT_MODE)
154 return 0; /* Nothing to do... */
155 else if (mode == NORMAL_VGA)
156 mode = VIDEO_80x25;
157 else if (mode == EXTENDED_VGA)
158 mode = VIDEO_8POINT;
159
160 rv = raw_set_mode(mode, &real_mode);
161 if (rv)
162 return rv;
163
164 if (mode & VIDEO_RECALC)
165 vga_recalc_vertical();
166
167 /* Save the canonical mode number for the kernel, not
168 an alias, size specification or menu position */
169#ifndef _WAKEUP
170 boot_params.hdr.vid_mode = real_mode;
171#endif
172 return 0;
173}