aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/boot
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
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')
-rw-r--r--arch/x86/boot/Makefile2
-rw-r--r--arch/x86/boot/boot.h5
-rw-r--r--arch/x86/boot/video-bios.c6
-rw-r--r--arch/x86/boot/video-mode.c173
-rw-r--r--arch/x86/boot/video-vesa.c8
-rw-r--r--arch/x86/boot/video-vga.c12
-rw-r--r--arch/x86/boot/video.c157
7 files changed, 204 insertions, 159 deletions
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
index 9695affeb584..7ee102f9c4f8 100644
--- a/arch/x86/boot/Makefile
+++ b/arch/x86/boot/Makefile
@@ -30,7 +30,7 @@ subdir- := compressed
30 30
31setup-y += a20.o cmdline.o copy.o cpu.o cpucheck.o edd.o 31setup-y += a20.o cmdline.o copy.o cpu.o cpucheck.o edd.o
32setup-y += header.o main.o mca.o memory.o pm.o pmjump.o 32setup-y += header.o main.o mca.o memory.o pm.o pmjump.o
33setup-y += printf.o string.o tty.o video.o version.o 33setup-y += printf.o string.o tty.o video.o video-mode.o version.o
34setup-$(CONFIG_X86_APM_BOOT) += apm.o 34setup-$(CONFIG_X86_APM_BOOT) += apm.o
35setup-$(CONFIG_X86_VOYAGER) += voyager.o 35setup-$(CONFIG_X86_VOYAGER) += voyager.o
36 36
diff --git a/arch/x86/boot/boot.h b/arch/x86/boot/boot.h
index 7822a4983da2..09578070bfba 100644
--- a/arch/x86/boot/boot.h
+++ b/arch/x86/boot/boot.h
@@ -286,6 +286,11 @@ int getchar_timeout(void);
286/* video.c */ 286/* video.c */
287void set_video(void); 287void set_video(void);
288 288
289/* video-mode.c */
290int set_mode(u16 mode);
291int mode_defined(u16 mode);
292void probe_cards(int unsafe);
293
289/* video-vesa.c */ 294/* video-vesa.c */
290void vesa_store_edid(void); 295void vesa_store_edid(void);
291 296
diff --git a/arch/x86/boot/video-bios.c b/arch/x86/boot/video-bios.c
index ff664a117096..39e247e96172 100644
--- a/arch/x86/boot/video-bios.c
+++ b/arch/x86/boot/video-bios.c
@@ -50,6 +50,7 @@ static int set_bios_mode(u8 mode)
50 if (new_mode == mode) 50 if (new_mode == mode)
51 return 0; /* Mode change OK */ 51 return 0; /* Mode change OK */
52 52
53#ifndef _WAKEUP
53 if (new_mode != boot_params.screen_info.orig_video_mode) { 54 if (new_mode != boot_params.screen_info.orig_video_mode) {
54 /* Mode setting failed, but we didn't end up where we 55 /* Mode setting failed, but we didn't end up where we
55 started. That's bad. Try to revert to the original 56 started. That's bad. Try to revert to the original
@@ -59,13 +60,18 @@ static int set_bios_mode(u8 mode)
59 : "+a" (ax) 60 : "+a" (ax)
60 : : "ebx", "ecx", "edx", "esi", "edi"); 61 : : "ebx", "ecx", "edx", "esi", "edi");
61 } 62 }
63#endif
62 return -1; 64 return -1;
63} 65}
64 66
65static int bios_probe(void) 67static int bios_probe(void)
66{ 68{
67 u8 mode; 69 u8 mode;
70#ifdef _WAKEUP
71 u8 saved_mode = 0x03;
72#else
68 u8 saved_mode = boot_params.screen_info.orig_video_mode; 73 u8 saved_mode = boot_params.screen_info.orig_video_mode;
74#endif
69 u16 crtc; 75 u16 crtc;
70 struct mode_info *mi; 76 struct mode_info *mi;
71 int nmodes = 0; 77 int nmodes = 0;
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}
diff --git a/arch/x86/boot/video-vesa.c b/arch/x86/boot/video-vesa.c
index 419b5c273374..5d5a3f6e8b5c 100644
--- a/arch/x86/boot/video-vesa.c
+++ b/arch/x86/boot/video-vesa.c
@@ -24,7 +24,11 @@ static struct vesa_mode_info vminfo;
24 24
25__videocard video_vesa; 25__videocard video_vesa;
26 26
27#ifndef _WAKEUP
27static void vesa_store_mode_params_graphics(void); 28static void vesa_store_mode_params_graphics(void);
29#else /* _WAKEUP */
30static inline void vesa_store_mode_params_graphics(void) {}
31#endif /* _WAKEUP */
28 32
29static int vesa_probe(void) 33static int vesa_probe(void)
30{ 34{
@@ -165,6 +169,8 @@ static int vesa_set_mode(struct mode_info *mode)
165} 169}
166 170
167 171
172#ifndef _WAKEUP
173
168/* Switch DAC to 8-bit mode */ 174/* Switch DAC to 8-bit mode */
169static void vesa_dac_set_8bits(void) 175static void vesa_dac_set_8bits(void)
170{ 176{
@@ -288,6 +294,8 @@ void vesa_store_edid(void)
288#endif /* CONFIG_FIRMWARE_EDID */ 294#endif /* CONFIG_FIRMWARE_EDID */
289} 295}
290 296
297#endif /* not _WAKEUP */
298
291__videocard video_vesa = 299__videocard video_vesa =
292{ 300{
293 .card_name = "VESA", 301 .card_name = "VESA",
diff --git a/arch/x86/boot/video-vga.c b/arch/x86/boot/video-vga.c
index 7259387b7d19..330d6589a2ad 100644
--- a/arch/x86/boot/video-vga.c
+++ b/arch/x86/boot/video-vga.c
@@ -210,6 +210,8 @@ static int vga_set_mode(struct mode_info *mode)
210 */ 210 */
211static int vga_probe(void) 211static int vga_probe(void)
212{ 212{
213 u16 ega_bx;
214
213 static const char *card_name[] = { 215 static const char *card_name[] = {
214 "CGA/MDA/HGC", "EGA", "VGA" 216 "CGA/MDA/HGC", "EGA", "VGA"
215 }; 217 };
@@ -226,12 +228,16 @@ static int vga_probe(void)
226 u8 vga_flag; 228 u8 vga_flag;
227 229
228 asm(INT10 230 asm(INT10
229 : "=b" (boot_params.screen_info.orig_video_ega_bx) 231 : "=b" (ega_bx)
230 : "a" (0x1200), "b" (0x10) /* Check EGA/VGA */ 232 : "a" (0x1200), "b" (0x10) /* Check EGA/VGA */
231 : "ecx", "edx", "esi", "edi"); 233 : "ecx", "edx", "esi", "edi");
232 234
235#ifndef _WAKEUP
236 boot_params.screen_info.orig_video_ega_bx = ega_bx;
237#endif
238
233 /* If we have MDA/CGA/HGC then BL will be unchanged at 0x10 */ 239 /* If we have MDA/CGA/HGC then BL will be unchanged at 0x10 */
234 if ((u8)boot_params.screen_info.orig_video_ega_bx != 0x10) { 240 if ((u8)ega_bx != 0x10) {
235 /* EGA/VGA */ 241 /* EGA/VGA */
236 asm(INT10 242 asm(INT10
237 : "=a" (vga_flag) 243 : "=a" (vga_flag)
@@ -240,7 +246,9 @@ static int vga_probe(void)
240 246
241 if (vga_flag == 0x1a) { 247 if (vga_flag == 0x1a) {
242 adapter = ADAPTER_VGA; 248 adapter = ADAPTER_VGA;
249#ifndef _WAKEUP
243 boot_params.screen_info.orig_video_isVGA = 1; 250 boot_params.screen_info.orig_video_isVGA = 1;
251#endif
244 } else { 252 } else {
245 adapter = ADAPTER_EGA; 253 adapter = ADAPTER_EGA;
246 } 254 }
diff --git a/arch/x86/boot/video.c b/arch/x86/boot/video.c
index 696d08f3843c..c1c47ba069ef 100644
--- a/arch/x86/boot/video.c
+++ b/arch/x86/boot/video.c
@@ -18,21 +18,6 @@
18#include "video.h" 18#include "video.h"
19#include "vesa.h" 19#include "vesa.h"
20 20
21/*
22 * Mode list variables
23 */
24static struct card_info cards[]; /* List of cards to probe for */
25
26/*
27 * Common variables
28 */
29int adapter; /* 0=CGA/MDA/HGC, 1=EGA, 2=VGA+ */
30u16 video_segment;
31int force_x, force_y; /* Don't query the BIOS for cols/rows */
32
33int do_restore = 0; /* Screen contents changed during mode flip */
34int graphic_mode; /* Graphic mode with linear frame buffer */
35
36static void store_cursor_position(void) 21static void store_cursor_position(void)
37{ 22{
38 u16 curpos; 23 u16 curpos;
@@ -107,147 +92,6 @@ static void store_mode_params(void)
107 boot_params.screen_info.orig_video_lines = y; 92 boot_params.screen_info.orig_video_lines = y;
108} 93}
109 94
110/* Probe the video drivers and have them generate their mode lists. */
111static void probe_cards(int unsafe)
112{
113 struct card_info *card;
114 static u8 probed[2];
115
116 if (probed[unsafe])
117 return;
118
119 probed[unsafe] = 1;
120
121 for (card = video_cards; card < video_cards_end; card++) {
122 if (card->unsafe == unsafe) {
123 if (card->probe)
124 card->nmodes = card->probe();
125 else
126 card->nmodes = 0;
127 }
128 }
129}
130
131/* Test if a mode is defined */
132int mode_defined(u16 mode)
133{
134 struct card_info *card;
135 struct mode_info *mi;
136 int i;
137
138 for (card = video_cards; card < video_cards_end; card++) {
139 mi = card->modes;
140 for (i = 0; i < card->nmodes; i++, mi++) {
141 if (mi->mode == mode)
142 return 1;
143 }
144 }
145
146 return 0;
147}
148
149/* Set mode (without recalc) */
150static int raw_set_mode(u16 mode, u16 *real_mode)
151{
152 int nmode, i;
153 struct card_info *card;
154 struct mode_info *mi;
155
156 /* Drop the recalc bit if set */
157 mode &= ~VIDEO_RECALC;
158
159 /* Scan for mode based on fixed ID, position, or resolution */
160 nmode = 0;
161 for (card = video_cards; card < video_cards_end; card++) {
162 mi = card->modes;
163 for (i = 0; i < card->nmodes; i++, mi++) {
164 int visible = mi->x || mi->y;
165
166 if ((mode == nmode && visible) ||
167 mode == mi->mode ||
168 mode == (mi->y << 8)+mi->x) {
169 *real_mode = mi->mode;
170 return card->set_mode(mi);
171 }
172
173 if (visible)
174 nmode++;
175 }
176 }
177
178 /* Nothing found? Is it an "exceptional" (unprobed) mode? */
179 for (card = video_cards; card < video_cards_end; card++) {
180 if (mode >= card->xmode_first &&
181 mode < card->xmode_first+card->xmode_n) {
182 struct mode_info mix;
183 *real_mode = mix.mode = mode;
184 mix.x = mix.y = 0;
185 return card->set_mode(&mix);
186 }
187 }
188
189 /* Otherwise, failure... */
190 return -1;
191}
192
193/*
194 * Recalculate the vertical video cutoff (hack!)
195 */
196static void vga_recalc_vertical(void)
197{
198 unsigned int font_size, rows;
199 u16 crtc;
200 u8 pt, ov;
201
202 set_fs(0);
203 font_size = rdfs8(0x485); /* BIOS: font size (pixels) */
204 rows = force_y ? force_y : rdfs8(0x484)+1; /* Text rows */
205
206 rows *= font_size; /* Visible scan lines */
207 rows--; /* ... minus one */
208
209 crtc = vga_crtc();
210
211 pt = in_idx(crtc, 0x11);
212 pt &= ~0x80; /* Unlock CR0-7 */
213 out_idx(pt, crtc, 0x11);
214
215 out_idx((u8)rows, crtc, 0x12); /* Lower height register */
216
217 ov = in_idx(crtc, 0x07); /* Overflow register */
218 ov &= 0xbd;
219 ov |= (rows >> (8-1)) & 0x02;
220 ov |= (rows >> (9-6)) & 0x40;
221 out_idx(ov, crtc, 0x07);
222}
223
224/* Set mode (with recalc if specified) */
225static int set_mode(u16 mode)
226{
227 int rv;
228 u16 real_mode;
229
230 /* Very special mode numbers... */
231 if (mode == VIDEO_CURRENT_MODE)
232 return 0; /* Nothing to do... */
233 else if (mode == NORMAL_VGA)
234 mode = VIDEO_80x25;
235 else if (mode == EXTENDED_VGA)
236 mode = VIDEO_8POINT;
237
238 rv = raw_set_mode(mode, &real_mode);
239 if (rv)
240 return rv;
241
242 if (mode & VIDEO_RECALC)
243 vga_recalc_vertical();
244
245 /* Save the canonical mode number for the kernel, not
246 an alias, size specification or menu position */
247 boot_params.hdr.vid_mode = real_mode;
248 return 0;
249}
250
251static unsigned int get_entry(void) 95static unsigned int get_entry(void)
252{ 96{
253 char entry_buf[4]; 97 char entry_buf[4];
@@ -486,6 +330,7 @@ void set_video(void)
486 printf("Undefined video mode number: %x\n", mode); 330 printf("Undefined video mode number: %x\n", mode);
487 mode = ASK_VGA; 331 mode = ASK_VGA;
488 } 332 }
333 boot_params.hdr.vid_mode = mode;
489 vesa_store_edid(); 334 vesa_store_edid();
490 store_mode_params(); 335 store_mode_params();
491 336