diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-10 19:14:41 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-10 19:14:41 -0400 |
commit | bec706838ec2f9c8c2b99e88a1270d7cba159b06 (patch) | |
tree | 96ec3ccbab3596dee79ef874483238853351a4f8 | |
parent | bb7762961d3ce745688e9050e914c1d3f980268d (diff) | |
parent | ee0736627d3347be0be2769fa7b26431f9726c9d (diff) |
Merge branch 'x86-setup-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'x86-setup-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
x86, setup: fix comment in the "glove box" code
x86, setup: "glove box" BIOS interrupts in the video code
x86, setup: "glove box" BIOS interrupts in the MCA code
x86, setup: "glove box" BIOS interrupts in the EDD code
x86, setup: "glove box" BIOS interrupts in the APM code
x86, setup: "glove box" BIOS interrupts in the core boot code
x86, setup: "glove box" BIOS calls -- infrastructure
-rw-r--r-- | arch/x86/boot/Makefile | 5 | ||||
-rw-r--r-- | arch/x86/boot/a20.c | 9 | ||||
-rw-r--r-- | arch/x86/boot/apm.c | 76 | ||||
-rw-r--r-- | arch/x86/boot/bioscall.S | 82 | ||||
-rw-r--r-- | arch/x86/boot/boot.h | 48 | ||||
-rw-r--r-- | arch/x86/boot/edd.c | 71 | ||||
-rw-r--r-- | arch/x86/boot/header.S | 2 | ||||
-rw-r--r-- | arch/x86/boot/main.c | 39 | ||||
-rw-r--r-- | arch/x86/boot/mca.c | 27 | ||||
-rw-r--r-- | arch/x86/boot/memory.c | 79 | ||||
-rw-r--r-- | arch/x86/boot/regs.c | 29 | ||||
-rw-r--r-- | arch/x86/boot/setup.ld | 6 | ||||
-rw-r--r-- | arch/x86/boot/tty.c | 52 | ||||
-rw-r--r-- | arch/x86/boot/video-bios.c | 27 | ||||
-rw-r--r-- | arch/x86/boot/video-vesa.c | 137 | ||||
-rw-r--r-- | arch/x86/boot/video-vga.c | 95 | ||||
-rw-r--r-- | arch/x86/boot/video.c | 42 | ||||
-rw-r--r-- | arch/x86/boot/video.h | 14 | ||||
-rw-r--r-- | arch/x86/kernel/acpi/realmode/Makefile | 2 | ||||
-rw-r--r-- | arch/x86/kernel/acpi/realmode/bioscall.S | 1 | ||||
-rw-r--r-- | arch/x86/kernel/acpi/realmode/regs.c | 1 |
21 files changed, 489 insertions, 355 deletions
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile index 619d297aa2ba..8d16ada25048 100644 --- a/arch/x86/boot/Makefile +++ b/arch/x86/boot/Makefile | |||
@@ -26,9 +26,10 @@ targets := vmlinux.bin setup.bin setup.elf bzImage | |||
26 | targets += fdimage fdimage144 fdimage288 image.iso mtools.conf | 26 | targets += fdimage fdimage144 fdimage288 image.iso mtools.conf |
27 | subdir- := compressed | 27 | subdir- := compressed |
28 | 28 | ||
29 | setup-y += a20.o cmdline.o copy.o cpu.o cpucheck.o edd.o | 29 | setup-y += a20.o bioscall.o cmdline.o copy.o cpu.o cpucheck.o edd.o |
30 | setup-y += header.o main.o mca.o memory.o pm.o pmjump.o | 30 | setup-y += header.o main.o mca.o memory.o pm.o pmjump.o |
31 | setup-y += printf.o string.o tty.o video.o video-mode.o version.o | 31 | setup-y += printf.o regs.o string.o tty.o video.o video-mode.o |
32 | setup-y += version.o | ||
32 | setup-$(CONFIG_X86_APM_BOOT) += apm.o | 33 | setup-$(CONFIG_X86_APM_BOOT) += apm.o |
33 | 34 | ||
34 | # The link order of the video-*.o modules can matter. In particular, | 35 | # The link order of the video-*.o modules can matter. In particular, |
diff --git a/arch/x86/boot/a20.c b/arch/x86/boot/a20.c index 7c19ce8c2442..64a31a6d751a 100644 --- a/arch/x86/boot/a20.c +++ b/arch/x86/boot/a20.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * | 2 | * |
3 | * Copyright (C) 1991, 1992 Linus Torvalds | 3 | * Copyright (C) 1991, 1992 Linus Torvalds |
4 | * Copyright 2007-2008 rPath, Inc. - All Rights Reserved | 4 | * Copyright 2007-2008 rPath, Inc. - All Rights Reserved |
5 | * Copyright 2009 Intel Corporation | 5 | * Copyright 2009 Intel Corporation; author H. Peter Anvin |
6 | * | 6 | * |
7 | * This file is part of the Linux kernel, and is made available under | 7 | * This file is part of the Linux kernel, and is made available under |
8 | * the terms of the GNU General Public License version 2. | 8 | * the terms of the GNU General Public License version 2. |
@@ -90,8 +90,11 @@ static int a20_test_long(void) | |||
90 | 90 | ||
91 | static void enable_a20_bios(void) | 91 | static void enable_a20_bios(void) |
92 | { | 92 | { |
93 | asm volatile("pushfl; int $0x15; popfl" | 93 | struct biosregs ireg; |
94 | : : "a" ((u16)0x2401)); | 94 | |
95 | initregs(&ireg); | ||
96 | ireg.ax = 0x2401; | ||
97 | intcall(0x15, &ireg, NULL); | ||
95 | } | 98 | } |
96 | 99 | ||
97 | static void enable_a20_kbc(void) | 100 | static void enable_a20_kbc(void) |
diff --git a/arch/x86/boot/apm.c b/arch/x86/boot/apm.c index 7aa6033001f9..ee274834ea8b 100644 --- a/arch/x86/boot/apm.c +++ b/arch/x86/boot/apm.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * | 2 | * |
3 | * Copyright (C) 1991, 1992 Linus Torvalds | 3 | * Copyright (C) 1991, 1992 Linus Torvalds |
4 | * Copyright 2007 rPath, Inc. - All Rights Reserved | 4 | * Copyright 2007 rPath, Inc. - All Rights Reserved |
5 | * Copyright 2009 Intel Corporation; author H. Peter Anvin | ||
5 | * | 6 | * |
6 | * Original APM BIOS checking by Stephen Rothwell, May 1994 | 7 | * Original APM BIOS checking by Stephen Rothwell, May 1994 |
7 | * (sfr@canb.auug.org.au) | 8 | * (sfr@canb.auug.org.au) |
@@ -19,75 +20,56 @@ | |||
19 | 20 | ||
20 | int query_apm_bios(void) | 21 | int query_apm_bios(void) |
21 | { | 22 | { |
22 | u16 ax, bx, cx, dx, di; | 23 | struct biosregs ireg, oreg; |
23 | u32 ebx, esi; | ||
24 | u8 err; | ||
25 | 24 | ||
26 | /* APM BIOS installation check */ | 25 | /* APM BIOS installation check */ |
27 | ax = 0x5300; | 26 | initregs(&ireg); |
28 | bx = cx = 0; | 27 | ireg.ah = 0x53; |
29 | asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp ; setc %0" | 28 | intcall(0x15, &ireg, &oreg); |
30 | : "=d" (err), "+a" (ax), "+b" (bx), "+c" (cx) | ||
31 | : : "esi", "edi"); | ||
32 | 29 | ||
33 | if (err) | 30 | if (oreg.flags & X86_EFLAGS_CF) |
34 | return -1; /* No APM BIOS */ | 31 | return -1; /* No APM BIOS */ |
35 | 32 | ||
36 | if (bx != 0x504d) /* "PM" signature */ | 33 | if (oreg.bx != 0x504d) /* "PM" signature */ |
37 | return -1; | 34 | return -1; |
38 | 35 | ||
39 | if (!(cx & 0x02)) /* 32 bits supported? */ | 36 | if (!(oreg.cx & 0x02)) /* 32 bits supported? */ |
40 | return -1; | 37 | return -1; |
41 | 38 | ||
42 | /* Disconnect first, just in case */ | 39 | /* Disconnect first, just in case */ |
43 | ax = 0x5304; | 40 | ireg.al = 0x04; |
44 | bx = 0; | 41 | intcall(0x15, &ireg, NULL); |
45 | asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp" | ||
46 | : "+a" (ax), "+b" (bx) | ||
47 | : : "ecx", "edx", "esi", "edi"); | ||
48 | |||
49 | /* Paranoia */ | ||
50 | ebx = esi = 0; | ||
51 | cx = dx = di = 0; | ||
52 | 42 | ||
53 | /* 32-bit connect */ | 43 | /* 32-bit connect */ |
54 | asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp ; setc %6" | 44 | ireg.al = 0x03; |
55 | : "=a" (ax), "+b" (ebx), "+c" (cx), "+d" (dx), | 45 | intcall(0x15, &ireg, &oreg); |
56 | "+S" (esi), "+D" (di), "=m" (err) | 46 | |
57 | : "a" (0x5303)); | 47 | boot_params.apm_bios_info.cseg = oreg.ax; |
58 | 48 | boot_params.apm_bios_info.offset = oreg.ebx; | |
59 | boot_params.apm_bios_info.cseg = ax; | 49 | boot_params.apm_bios_info.cseg_16 = oreg.cx; |
60 | boot_params.apm_bios_info.offset = ebx; | 50 | boot_params.apm_bios_info.dseg = oreg.dx; |
61 | boot_params.apm_bios_info.cseg_16 = cx; | 51 | boot_params.apm_bios_info.cseg_len = oreg.si; |
62 | boot_params.apm_bios_info.dseg = dx; | 52 | boot_params.apm_bios_info.cseg_16_len = oreg.hsi; |
63 | boot_params.apm_bios_info.cseg_len = (u16)esi; | 53 | boot_params.apm_bios_info.dseg_len = oreg.di; |
64 | boot_params.apm_bios_info.cseg_16_len = esi >> 16; | 54 | |
65 | boot_params.apm_bios_info.dseg_len = di; | 55 | if (oreg.flags & X86_EFLAGS_CF) |
66 | |||
67 | if (err) | ||
68 | return -1; | 56 | return -1; |
69 | 57 | ||
70 | /* Redo the installation check as the 32-bit connect; | 58 | /* Redo the installation check as the 32-bit connect; |
71 | some BIOSes return different flags this way... */ | 59 | some BIOSes return different flags this way... */ |
72 | 60 | ||
73 | ax = 0x5300; | 61 | ireg.al = 0x00; |
74 | bx = cx = 0; | 62 | intcall(0x15, &ireg, &oreg); |
75 | asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp ; setc %0" | ||
76 | : "=d" (err), "+a" (ax), "+b" (bx), "+c" (cx) | ||
77 | : : "esi", "edi"); | ||
78 | 63 | ||
79 | if (err || bx != 0x504d) { | 64 | if ((oreg.eflags & X86_EFLAGS_CF) || oreg.bx != 0x504d) { |
80 | /* Failure with 32-bit connect, try to disconect and ignore */ | 65 | /* Failure with 32-bit connect, try to disconect and ignore */ |
81 | ax = 0x5304; | 66 | ireg.al = 0x04; |
82 | bx = 0; | 67 | intcall(0x15, &ireg, NULL); |
83 | asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp" | ||
84 | : "+a" (ax), "+b" (bx) | ||
85 | : : "ecx", "edx", "esi", "edi"); | ||
86 | return -1; | 68 | return -1; |
87 | } | 69 | } |
88 | 70 | ||
89 | boot_params.apm_bios_info.version = ax; | 71 | boot_params.apm_bios_info.version = oreg.ax; |
90 | boot_params.apm_bios_info.flags = cx; | 72 | boot_params.apm_bios_info.flags = oreg.cx; |
91 | return 0; | 73 | return 0; |
92 | } | 74 | } |
93 | 75 | ||
diff --git a/arch/x86/boot/bioscall.S b/arch/x86/boot/bioscall.S new file mode 100644 index 000000000000..507793739ea5 --- /dev/null +++ b/arch/x86/boot/bioscall.S | |||
@@ -0,0 +1,82 @@ | |||
1 | /* ----------------------------------------------------------------------- | ||
2 | * | ||
3 | * Copyright 2009 Intel Corporation; author H. Peter Anvin | ||
4 | * | ||
5 | * This file is part of the Linux kernel, and is made available under | ||
6 | * the terms of the GNU General Public License version 2 or (at your | ||
7 | * option) any later version; incorporated herein by reference. | ||
8 | * | ||
9 | * ----------------------------------------------------------------------- */ | ||
10 | |||
11 | /* | ||
12 | * "Glove box" for BIOS calls. Avoids the constant problems with BIOSes | ||
13 | * touching registers they shouldn't be. | ||
14 | */ | ||
15 | |||
16 | .code16 | ||
17 | .text | ||
18 | .globl intcall | ||
19 | .type intcall, @function | ||
20 | intcall: | ||
21 | /* Self-modify the INT instruction. Ugly, but works. */ | ||
22 | cmpb %al, 3f | ||
23 | je 1f | ||
24 | movb %al, 3f | ||
25 | jmp 1f /* Synchronize pipeline */ | ||
26 | 1: | ||
27 | /* Save state */ | ||
28 | pushfl | ||
29 | pushw %fs | ||
30 | pushw %gs | ||
31 | pushal | ||
32 | |||
33 | /* Copy input state to stack frame */ | ||
34 | subw $44, %sp | ||
35 | movw %dx, %si | ||
36 | movw %sp, %di | ||
37 | movw $11, %cx | ||
38 | rep; movsd | ||
39 | |||
40 | /* Pop full state from the stack */ | ||
41 | popal | ||
42 | popw %gs | ||
43 | popw %fs | ||
44 | popw %es | ||
45 | popw %ds | ||
46 | popfl | ||
47 | |||
48 | /* Actual INT */ | ||
49 | .byte 0xcd /* INT opcode */ | ||
50 | 3: .byte 0 | ||
51 | |||
52 | /* Push full state to the stack */ | ||
53 | pushfl | ||
54 | pushw %ds | ||
55 | pushw %es | ||
56 | pushw %fs | ||
57 | pushw %gs | ||
58 | pushal | ||
59 | |||
60 | /* Re-establish C environment invariants */ | ||
61 | cld | ||
62 | movzwl %sp, %esp | ||
63 | movw %cs, %ax | ||
64 | movw %ax, %ds | ||
65 | movw %ax, %es | ||
66 | |||
67 | /* Copy output state from stack frame */ | ||
68 | movw 68(%esp), %di /* Original %cx == 3rd argument */ | ||
69 | andw %di, %di | ||
70 | jz 4f | ||
71 | movw %sp, %si | ||
72 | movw $11, %cx | ||
73 | rep; movsd | ||
74 | 4: addw $44, %sp | ||
75 | |||
76 | /* Restore state and return */ | ||
77 | popal | ||
78 | popw %gs | ||
79 | popw %fs | ||
80 | popfl | ||
81 | retl | ||
82 | .size intcall, .-intcall | ||
diff --git a/arch/x86/boot/boot.h b/arch/x86/boot/boot.h index 7b2692e897e5..98239d2658f2 100644 --- a/arch/x86/boot/boot.h +++ b/arch/x86/boot/boot.h | |||
@@ -2,6 +2,7 @@ | |||
2 | * | 2 | * |
3 | * Copyright (C) 1991, 1992 Linus Torvalds | 3 | * Copyright (C) 1991, 1992 Linus Torvalds |
4 | * Copyright 2007 rPath, Inc. - All Rights Reserved | 4 | * Copyright 2007 rPath, Inc. - All Rights Reserved |
5 | * Copyright 2009 Intel Corporation; author H. Peter Anvin | ||
5 | * | 6 | * |
6 | * This file is part of the Linux kernel, and is made available under | 7 | * 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 | * the terms of the GNU General Public License version 2. |
@@ -26,6 +27,7 @@ | |||
26 | #include <asm/setup.h> | 27 | #include <asm/setup.h> |
27 | #include "bitops.h" | 28 | #include "bitops.h" |
28 | #include <asm/cpufeature.h> | 29 | #include <asm/cpufeature.h> |
30 | #include <asm/processor-flags.h> | ||
29 | 31 | ||
30 | /* Useful macros */ | 32 | /* Useful macros */ |
31 | #define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) | 33 | #define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) |
@@ -241,6 +243,49 @@ int enable_a20(void); | |||
241 | /* apm.c */ | 243 | /* apm.c */ |
242 | int query_apm_bios(void); | 244 | int query_apm_bios(void); |
243 | 245 | ||
246 | /* bioscall.c */ | ||
247 | struct biosregs { | ||
248 | union { | ||
249 | struct { | ||
250 | u32 edi; | ||
251 | u32 esi; | ||
252 | u32 ebp; | ||
253 | u32 _esp; | ||
254 | u32 ebx; | ||
255 | u32 edx; | ||
256 | u32 ecx; | ||
257 | u32 eax; | ||
258 | u32 _fsgs; | ||
259 | u32 _dses; | ||
260 | u32 eflags; | ||
261 | }; | ||
262 | struct { | ||
263 | u16 di, hdi; | ||
264 | u16 si, hsi; | ||
265 | u16 bp, hbp; | ||
266 | u16 _sp, _hsp; | ||
267 | u16 bx, hbx; | ||
268 | u16 dx, hdx; | ||
269 | u16 cx, hcx; | ||
270 | u16 ax, hax; | ||
271 | u16 gs, fs; | ||
272 | u16 es, ds; | ||
273 | u16 flags, hflags; | ||
274 | }; | ||
275 | struct { | ||
276 | u8 dil, dih, edi2, edi3; | ||
277 | u8 sil, sih, esi2, esi3; | ||
278 | u8 bpl, bph, ebp2, ebp3; | ||
279 | u8 _spl, _sph, _esp2, _esp3; | ||
280 | u8 bl, bh, ebx2, ebx3; | ||
281 | u8 dl, dh, edx2, edx3; | ||
282 | u8 cl, ch, ecx2, ecx3; | ||
283 | u8 al, ah, eax2, eax3; | ||
284 | }; | ||
285 | }; | ||
286 | }; | ||
287 | void intcall(u8 int_no, const struct biosregs *ireg, struct biosregs *oreg); | ||
288 | |||
244 | /* cmdline.c */ | 289 | /* cmdline.c */ |
245 | int cmdline_find_option(const char *option, char *buffer, int bufsize); | 290 | int cmdline_find_option(const char *option, char *buffer, int bufsize); |
246 | int cmdline_find_option_bool(const char *option); | 291 | int cmdline_find_option_bool(const char *option); |
@@ -279,6 +324,9 @@ int sprintf(char *buf, const char *fmt, ...); | |||
279 | int vsprintf(char *buf, const char *fmt, va_list args); | 324 | int vsprintf(char *buf, const char *fmt, va_list args); |
280 | int printf(const char *fmt, ...); | 325 | int printf(const char *fmt, ...); |
281 | 326 | ||
327 | /* regs.c */ | ||
328 | void initregs(struct biosregs *regs); | ||
329 | |||
282 | /* string.c */ | 330 | /* string.c */ |
283 | int strcmp(const char *str1, const char *str2); | 331 | int strcmp(const char *str1, const char *str2); |
284 | size_t strnlen(const char *s, size_t maxlen); | 332 | size_t strnlen(const char *s, size_t maxlen); |
diff --git a/arch/x86/boot/edd.c b/arch/x86/boot/edd.c index 1aae8f3e5ca1..c501a5b466f8 100644 --- a/arch/x86/boot/edd.c +++ b/arch/x86/boot/edd.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * | 2 | * |
3 | * Copyright (C) 1991, 1992 Linus Torvalds | 3 | * Copyright (C) 1991, 1992 Linus Torvalds |
4 | * Copyright 2007 rPath, Inc. - All Rights Reserved | 4 | * Copyright 2007 rPath, Inc. - All Rights Reserved |
5 | * Copyright 2009 Intel Corporation; author H. Peter Anvin | ||
5 | * | 6 | * |
6 | * This file is part of the Linux kernel, and is made available under | 7 | * 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 | * the terms of the GNU General Public License version 2. |
@@ -22,17 +23,17 @@ | |||
22 | */ | 23 | */ |
23 | static int read_mbr(u8 devno, void *buf) | 24 | static int read_mbr(u8 devno, void *buf) |
24 | { | 25 | { |
25 | u16 ax, bx, cx, dx; | 26 | struct biosregs ireg, oreg; |
26 | 27 | ||
27 | ax = 0x0201; /* Legacy Read, one sector */ | 28 | initregs(&ireg); |
28 | cx = 0x0001; /* Sector 0-0-1 */ | 29 | ireg.ax = 0x0201; /* Legacy Read, one sector */ |
29 | dx = devno; | 30 | ireg.cx = 0x0001; /* Sector 0-0-1 */ |
30 | bx = (size_t)buf; | 31 | ireg.dl = devno; |
31 | asm volatile("pushfl; stc; int $0x13; setc %%al; popfl" | 32 | ireg.bx = (size_t)buf; |
32 | : "+a" (ax), "+c" (cx), "+d" (dx), "+b" (bx) | ||
33 | : : "esi", "edi", "memory"); | ||
34 | 33 | ||
35 | return -(u8)ax; /* 0 or -1 */ | 34 | intcall(0x13, &ireg, &oreg); |
35 | |||
36 | return -(oreg.eflags & X86_EFLAGS_CF); /* 0 or -1 */ | ||
36 | } | 37 | } |
37 | 38 | ||
38 | static u32 read_mbr_sig(u8 devno, struct edd_info *ei, u32 *mbrsig) | 39 | static u32 read_mbr_sig(u8 devno, struct edd_info *ei, u32 *mbrsig) |
@@ -72,56 +73,46 @@ static u32 read_mbr_sig(u8 devno, struct edd_info *ei, u32 *mbrsig) | |||
72 | 73 | ||
73 | static int get_edd_info(u8 devno, struct edd_info *ei) | 74 | static int get_edd_info(u8 devno, struct edd_info *ei) |
74 | { | 75 | { |
75 | u16 ax, bx, cx, dx, di; | 76 | struct biosregs ireg, oreg; |
76 | 77 | ||
77 | memset(ei, 0, sizeof *ei); | 78 | memset(ei, 0, sizeof *ei); |
78 | 79 | ||
79 | /* Check Extensions Present */ | 80 | /* Check Extensions Present */ |
80 | 81 | ||
81 | ax = 0x4100; | 82 | initregs(&ireg); |
82 | bx = EDDMAGIC1; | 83 | ireg.ah = 0x41; |
83 | dx = devno; | 84 | ireg.bx = EDDMAGIC1; |
84 | asm("pushfl; stc; int $0x13; setc %%al; popfl" | 85 | ireg.dl = devno; |
85 | : "+a" (ax), "+b" (bx), "=c" (cx), "+d" (dx) | 86 | intcall(0x13, &ireg, &oreg); |
86 | : : "esi", "edi"); | ||
87 | 87 | ||
88 | if ((u8)ax) | 88 | if (oreg.eflags & X86_EFLAGS_CF) |
89 | return -1; /* No extended information */ | 89 | return -1; /* No extended information */ |
90 | 90 | ||
91 | if (bx != EDDMAGIC2) | 91 | if (oreg.bx != EDDMAGIC2) |
92 | return -1; | 92 | return -1; |
93 | 93 | ||
94 | ei->device = devno; | 94 | ei->device = devno; |
95 | ei->version = ax >> 8; /* EDD version number */ | 95 | ei->version = oreg.ah; /* EDD version number */ |
96 | ei->interface_support = cx; /* EDD functionality subsets */ | 96 | ei->interface_support = oreg.cx; /* EDD functionality subsets */ |
97 | 97 | ||
98 | /* Extended Get Device Parameters */ | 98 | /* Extended Get Device Parameters */ |
99 | 99 | ||
100 | ei->params.length = sizeof(ei->params); | 100 | ei->params.length = sizeof(ei->params); |
101 | ax = 0x4800; | 101 | ireg.ah = 0x48; |
102 | dx = devno; | 102 | ireg.si = (size_t)&ei->params; |
103 | asm("pushfl; int $0x13; popfl" | 103 | intcall(0x13, &ireg, &oreg); |
104 | : "+a" (ax), "+d" (dx), "=m" (ei->params) | ||
105 | : "S" (&ei->params) | ||
106 | : "ebx", "ecx", "edi"); | ||
107 | 104 | ||
108 | /* Get legacy CHS parameters */ | 105 | /* Get legacy CHS parameters */ |
109 | 106 | ||
110 | /* Ralf Brown recommends setting ES:DI to 0:0 */ | 107 | /* Ralf Brown recommends setting ES:DI to 0:0 */ |
111 | ax = 0x0800; | 108 | ireg.ah = 0x08; |
112 | dx = devno; | 109 | ireg.es = 0; |
113 | di = 0; | 110 | intcall(0x13, &ireg, &oreg); |
114 | asm("pushw %%es; " | 111 | |
115 | "movw %%di,%%es; " | 112 | if (!(oreg.eflags & X86_EFLAGS_CF)) { |
116 | "pushfl; stc; int $0x13; setc %%al; popfl; " | 113 | ei->legacy_max_cylinder = oreg.ch + ((oreg.cl & 0xc0) << 2); |
117 | "popw %%es" | 114 | ei->legacy_max_head = oreg.dh; |
118 | : "+a" (ax), "=b" (bx), "=c" (cx), "+d" (dx), "+D" (di) | 115 | ei->legacy_sectors_per_track = oreg.cl & 0x3f; |
119 | : : "esi"); | ||
120 | |||
121 | if ((u8)ax == 0) { | ||
122 | ei->legacy_max_cylinder = (cx >> 8) + ((cx & 0xc0) << 2); | ||
123 | ei->legacy_max_head = dx >> 8; | ||
124 | ei->legacy_sectors_per_track = cx & 0x3f; | ||
125 | } | 116 | } |
126 | 117 | ||
127 | return 0; | 118 | return 0; |
diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S index 1040f6e8010c..b31cc54b4641 100644 --- a/arch/x86/boot/header.S +++ b/arch/x86/boot/header.S | |||
@@ -237,7 +237,7 @@ init_size: .long INIT_SIZE # kernel initialization size | |||
237 | 237 | ||
238 | # End of setup header ##################################################### | 238 | # End of setup header ##################################################### |
239 | 239 | ||
240 | .section ".inittext", "ax" | 240 | .section ".entrytext", "ax" |
241 | start_of_setup: | 241 | start_of_setup: |
242 | #ifdef SAFE_RESET_DISK_CONTROLLER | 242 | #ifdef SAFE_RESET_DISK_CONTROLLER |
243 | # Reset the disk controller. | 243 | # Reset the disk controller. |
diff --git a/arch/x86/boot/main.c b/arch/x86/boot/main.c index 58f0415d3ae0..140172b895bd 100644 --- a/arch/x86/boot/main.c +++ b/arch/x86/boot/main.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * | 2 | * |
3 | * Copyright (C) 1991, 1992 Linus Torvalds | 3 | * Copyright (C) 1991, 1992 Linus Torvalds |
4 | * Copyright 2007 rPath, Inc. - All Rights Reserved | 4 | * Copyright 2007 rPath, Inc. - All Rights Reserved |
5 | * Copyright 2009 Intel Corporation; author H. Peter Anvin | ||
5 | * | 6 | * |
6 | * This file is part of the Linux kernel, and is made available under | 7 | * 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 | * the terms of the GNU General Public License version 2. |
@@ -61,11 +62,10 @@ static void copy_boot_params(void) | |||
61 | */ | 62 | */ |
62 | static void keyboard_set_repeat(void) | 63 | static void keyboard_set_repeat(void) |
63 | { | 64 | { |
64 | u16 ax = 0x0305; | 65 | struct biosregs ireg; |
65 | u16 bx = 0; | 66 | initregs(&ireg); |
66 | asm volatile("int $0x16" | 67 | ireg.ax = 0x0305; |
67 | : "+a" (ax), "+b" (bx) | 68 | intcall(0x16, &ireg, NULL); |
68 | : : "ecx", "edx", "esi", "edi"); | ||
69 | } | 69 | } |
70 | 70 | ||
71 | /* | 71 | /* |
@@ -73,18 +73,22 @@ static void keyboard_set_repeat(void) | |||
73 | */ | 73 | */ |
74 | static void query_ist(void) | 74 | static void query_ist(void) |
75 | { | 75 | { |
76 | struct biosregs ireg, oreg; | ||
77 | |||
76 | /* Some older BIOSes apparently crash on this call, so filter | 78 | /* Some older BIOSes apparently crash on this call, so filter |
77 | it from machines too old to have SpeedStep at all. */ | 79 | it from machines too old to have SpeedStep at all. */ |
78 | if (cpu.level < 6) | 80 | if (cpu.level < 6) |
79 | return; | 81 | return; |
80 | 82 | ||
81 | asm("int $0x15" | 83 | initregs(&ireg); |
82 | : "=a" (boot_params.ist_info.signature), | 84 | ireg.ax = 0xe980; /* IST Support */ |
83 | "=b" (boot_params.ist_info.command), | 85 | ireg.edx = 0x47534943; /* Request value */ |
84 | "=c" (boot_params.ist_info.event), | 86 | intcall(0x15, &ireg, &oreg); |
85 | "=d" (boot_params.ist_info.perf_level) | 87 | |
86 | : "a" (0x0000e980), /* IST Support */ | 88 | boot_params.ist_info.signature = oreg.eax; |
87 | "d" (0x47534943)); /* Request value */ | 89 | boot_params.ist_info.command = oreg.ebx; |
90 | boot_params.ist_info.event = oreg.ecx; | ||
91 | boot_params.ist_info.perf_level = oreg.edx; | ||
88 | } | 92 | } |
89 | 93 | ||
90 | /* | 94 | /* |
@@ -93,13 +97,12 @@ static void query_ist(void) | |||
93 | static void set_bios_mode(void) | 97 | static void set_bios_mode(void) |
94 | { | 98 | { |
95 | #ifdef CONFIG_X86_64 | 99 | #ifdef CONFIG_X86_64 |
96 | u32 eax, ebx; | 100 | struct biosregs ireg; |
97 | 101 | ||
98 | eax = 0xec00; | 102 | initregs(&ireg); |
99 | ebx = 2; | 103 | ireg.ax = 0xec00; |
100 | asm volatile("int $0x15" | 104 | ireg.bx = 2; |
101 | : "+a" (eax), "+b" (ebx) | 105 | intcall(0x15, &ireg, NULL); |
102 | : : "ecx", "edx", "esi", "edi"); | ||
103 | #endif | 106 | #endif |
104 | } | 107 | } |
105 | 108 | ||
diff --git a/arch/x86/boot/mca.c b/arch/x86/boot/mca.c index 911eaae5d696..a95a531148ef 100644 --- a/arch/x86/boot/mca.c +++ b/arch/x86/boot/mca.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * | 2 | * |
3 | * Copyright (C) 1991, 1992 Linus Torvalds | 3 | * Copyright (C) 1991, 1992 Linus Torvalds |
4 | * Copyright 2007 rPath, Inc. - All Rights Reserved | 4 | * Copyright 2007 rPath, Inc. - All Rights Reserved |
5 | * Copyright 2009 Intel Corporation; author H. Peter Anvin | ||
5 | * | 6 | * |
6 | * This file is part of the Linux kernel, and is made available under | 7 | * 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 | * the terms of the GNU General Public License version 2. |
@@ -16,26 +17,22 @@ | |||
16 | 17 | ||
17 | int query_mca(void) | 18 | int query_mca(void) |
18 | { | 19 | { |
19 | u8 err; | 20 | struct biosregs ireg, oreg; |
20 | u16 es, bx, len; | 21 | u16 len; |
21 | 22 | ||
22 | asm("pushw %%es ; " | 23 | initregs(&ireg); |
23 | "int $0x15 ; " | 24 | ireg.ah = 0xc0; |
24 | "setc %0 ; " | 25 | intcall(0x15, &ireg, &oreg); |
25 | "movw %%es, %1 ; " | 26 | |
26 | "popw %%es" | 27 | if (oreg.eflags & X86_EFLAGS_CF) |
27 | : "=acd" (err), "=acdSD" (es), "=b" (bx) | ||
28 | : "a" (0xc000)); | ||
29 | |||
30 | if (err) | ||
31 | return -1; /* No MCA present */ | 28 | return -1; /* No MCA present */ |
32 | 29 | ||
33 | set_fs(es); | 30 | set_fs(oreg.es); |
34 | len = rdfs16(bx); | 31 | len = rdfs16(oreg.bx); |
35 | 32 | ||
36 | if (len > sizeof(boot_params.sys_desc_table)) | 33 | if (len > sizeof(boot_params.sys_desc_table)) |
37 | len = sizeof(boot_params.sys_desc_table); | 34 | len = sizeof(boot_params.sys_desc_table); |
38 | 35 | ||
39 | copy_from_fs(&boot_params.sys_desc_table, bx, len); | 36 | copy_from_fs(&boot_params.sys_desc_table, oreg.bx, len); |
40 | return 0; | 37 | return 0; |
41 | } | 38 | } |
diff --git a/arch/x86/boot/memory.c b/arch/x86/boot/memory.c index 74b3d2ba84e9..cae3feb1035e 100644 --- a/arch/x86/boot/memory.c +++ b/arch/x86/boot/memory.c | |||
@@ -20,12 +20,16 @@ | |||
20 | static int detect_memory_e820(void) | 20 | static int detect_memory_e820(void) |
21 | { | 21 | { |
22 | int count = 0; | 22 | int count = 0; |
23 | u32 next = 0; | 23 | struct biosregs ireg, oreg; |
24 | u32 size, id, edi; | ||
25 | u8 err; | ||
26 | struct e820entry *desc = boot_params.e820_map; | 24 | struct e820entry *desc = boot_params.e820_map; |
27 | static struct e820entry buf; /* static so it is zeroed */ | 25 | static struct e820entry buf; /* static so it is zeroed */ |
28 | 26 | ||
27 | initregs(&ireg); | ||
28 | ireg.ax = 0xe820; | ||
29 | ireg.cx = sizeof buf; | ||
30 | ireg.edx = SMAP; | ||
31 | ireg.di = (size_t)&buf; | ||
32 | |||
29 | /* | 33 | /* |
30 | * Note: at least one BIOS is known which assumes that the | 34 | * Note: at least one BIOS is known which assumes that the |
31 | * buffer pointed to by one e820 call is the same one as | 35 | * buffer pointed to by one e820 call is the same one as |
@@ -41,22 +45,13 @@ static int detect_memory_e820(void) | |||
41 | */ | 45 | */ |
42 | 46 | ||
43 | do { | 47 | do { |
44 | size = sizeof buf; | 48 | intcall(0x15, &ireg, &oreg); |
45 | 49 | ireg.ebx = oreg.ebx; /* for next iteration... */ | |
46 | /* Important: %edx and %esi are clobbered by some BIOSes, | ||
47 | so they must be either used for the error output | ||
48 | or explicitly marked clobbered. Given that, assume there | ||
49 | is something out there clobbering %ebp and %edi, too. */ | ||
50 | asm("pushl %%ebp; int $0x15; popl %%ebp; setc %0" | ||
51 | : "=d" (err), "+b" (next), "=a" (id), "+c" (size), | ||
52 | "=D" (edi), "+m" (buf) | ||
53 | : "D" (&buf), "d" (SMAP), "a" (0xe820) | ||
54 | : "esi"); | ||
55 | 50 | ||
56 | /* BIOSes which terminate the chain with CF = 1 as opposed | 51 | /* BIOSes which terminate the chain with CF = 1 as opposed |
57 | to %ebx = 0 don't always report the SMAP signature on | 52 | to %ebx = 0 don't always report the SMAP signature on |
58 | the final, failing, probe. */ | 53 | the final, failing, probe. */ |
59 | if (err) | 54 | if (oreg.eflags & X86_EFLAGS_CF) |
60 | break; | 55 | break; |
61 | 56 | ||
62 | /* Some BIOSes stop returning SMAP in the middle of | 57 | /* Some BIOSes stop returning SMAP in the middle of |
@@ -64,60 +59,64 @@ static int detect_memory_e820(void) | |||
64 | screwed up the map at that point, we might have a | 59 | screwed up the map at that point, we might have a |
65 | partial map, the full map, or complete garbage, so | 60 | partial map, the full map, or complete garbage, so |
66 | just return failure. */ | 61 | just return failure. */ |
67 | if (id != SMAP) { | 62 | if (oreg.eax != SMAP) { |
68 | count = 0; | 63 | count = 0; |
69 | break; | 64 | break; |
70 | } | 65 | } |
71 | 66 | ||
72 | *desc++ = buf; | 67 | *desc++ = buf; |
73 | count++; | 68 | count++; |
74 | } while (next && count < ARRAY_SIZE(boot_params.e820_map)); | 69 | } while (ireg.ebx && count < ARRAY_SIZE(boot_params.e820_map)); |
75 | 70 | ||
76 | return boot_params.e820_entries = count; | 71 | return boot_params.e820_entries = count; |
77 | } | 72 | } |
78 | 73 | ||
79 | static int detect_memory_e801(void) | 74 | static int detect_memory_e801(void) |
80 | { | 75 | { |
81 | u16 ax, bx, cx, dx; | 76 | struct biosregs ireg, oreg; |
82 | u8 err; | ||
83 | 77 | ||
84 | bx = cx = dx = 0; | 78 | initregs(&ireg); |
85 | ax = 0xe801; | 79 | ireg.ax = 0xe801; |
86 | asm("stc; int $0x15; setc %0" | 80 | intcall(0x15, &ireg, &oreg); |
87 | : "=m" (err), "+a" (ax), "+b" (bx), "+c" (cx), "+d" (dx)); | ||
88 | 81 | ||
89 | if (err) | 82 | if (oreg.eflags & X86_EFLAGS_CF) |
90 | return -1; | 83 | return -1; |
91 | 84 | ||
92 | /* Do we really need to do this? */ | 85 | /* Do we really need to do this? */ |
93 | if (cx || dx) { | 86 | if (oreg.cx || oreg.dx) { |
94 | ax = cx; | 87 | oreg.ax = oreg.cx; |
95 | bx = dx; | 88 | oreg.bx = oreg.dx; |
96 | } | 89 | } |
97 | 90 | ||
98 | if (ax > 15*1024) | 91 | if (oreg.ax > 15*1024) { |
99 | return -1; /* Bogus! */ | 92 | return -1; /* Bogus! */ |
100 | 93 | } else if (oreg.ax == 15*1024) { | |
101 | /* This ignores memory above 16MB if we have a memory hole | 94 | boot_params.alt_mem_k = (oreg.dx << 6) + oreg.ax; |
102 | there. If someone actually finds a machine with a memory | 95 | } else { |
103 | hole at 16MB and no support for 0E820h they should probably | 96 | /* |
104 | generate a fake e820 map. */ | 97 | * This ignores memory above 16MB if we have a memory |
105 | boot_params.alt_mem_k = (ax == 15*1024) ? (dx << 6)+ax : ax; | 98 | * hole there. If someone actually finds a machine |
99 | * with a memory hole at 16MB and no support for | ||
100 | * 0E820h they should probably generate a fake e820 | ||
101 | * map. | ||
102 | */ | ||
103 | boot_params.alt_mem_k = oreg.ax; | ||
104 | } | ||
106 | 105 | ||
107 | return 0; | 106 | return 0; |
108 | } | 107 | } |
109 | 108 | ||
110 | static int detect_memory_88(void) | 109 | static int detect_memory_88(void) |
111 | { | 110 | { |
112 | u16 ax; | 111 | struct biosregs ireg, oreg; |
113 | u8 err; | ||
114 | 112 | ||
115 | ax = 0x8800; | 113 | initregs(&ireg); |
116 | asm("stc; int $0x15; setc %0" : "=bcdm" (err), "+a" (ax)); | 114 | ireg.ah = 0x88; |
115 | intcall(0x15, &ireg, &oreg); | ||
117 | 116 | ||
118 | boot_params.screen_info.ext_mem_k = ax; | 117 | boot_params.screen_info.ext_mem_k = oreg.ax; |
119 | 118 | ||
120 | return -err; | 119 | return -(oreg.eflags & X86_EFLAGS_CF); /* 0 or -1 */ |
121 | } | 120 | } |
122 | 121 | ||
123 | int detect_memory(void) | 122 | int detect_memory(void) |
diff --git a/arch/x86/boot/regs.c b/arch/x86/boot/regs.c new file mode 100644 index 000000000000..958019b1cfa5 --- /dev/null +++ b/arch/x86/boot/regs.c | |||
@@ -0,0 +1,29 @@ | |||
1 | /* ----------------------------------------------------------------------- | ||
2 | * | ||
3 | * Copyright 2009 Intel Corporation; author H. Peter Anvin | ||
4 | * | ||
5 | * This file is part of the Linux kernel, and is made available under | ||
6 | * the terms of the GNU General Public License version 2 or (at your | ||
7 | * option) any later version; incorporated herein by reference. | ||
8 | * | ||
9 | * ----------------------------------------------------------------------- */ | ||
10 | |||
11 | /* | ||
12 | * Simple helper function for initializing a register set. | ||
13 | * | ||
14 | * Note that this sets EFLAGS_CF in the input register set; this | ||
15 | * makes it easier to catch functions which do nothing but don't | ||
16 | * explicitly set CF. | ||
17 | */ | ||
18 | |||
19 | #include "boot.h" | ||
20 | |||
21 | void initregs(struct biosregs *reg) | ||
22 | { | ||
23 | memset(reg, 0, sizeof *reg); | ||
24 | reg->eflags |= X86_EFLAGS_CF; | ||
25 | reg->ds = ds(); | ||
26 | reg->es = ds(); | ||
27 | reg->fs = fs(); | ||
28 | reg->gs = gs(); | ||
29 | } | ||
diff --git a/arch/x86/boot/setup.ld b/arch/x86/boot/setup.ld index bb8dc2de7969..0f6ec455a2b1 100644 --- a/arch/x86/boot/setup.ld +++ b/arch/x86/boot/setup.ld | |||
@@ -15,8 +15,11 @@ SECTIONS | |||
15 | 15 | ||
16 | . = 497; | 16 | . = 497; |
17 | .header : { *(.header) } | 17 | .header : { *(.header) } |
18 | .entrytext : { *(.entrytext) } | ||
18 | .inittext : { *(.inittext) } | 19 | .inittext : { *(.inittext) } |
19 | .initdata : { *(.initdata) } | 20 | .initdata : { *(.initdata) } |
21 | __end_init = .; | ||
22 | |||
20 | .text : { *(.text) } | 23 | .text : { *(.text) } |
21 | .text32 : { *(.text32) } | 24 | .text32 : { *(.text32) } |
22 | 25 | ||
@@ -52,4 +55,7 @@ SECTIONS | |||
52 | 55 | ||
53 | . = ASSERT(_end <= 0x8000, "Setup too big!"); | 56 | . = ASSERT(_end <= 0x8000, "Setup too big!"); |
54 | . = ASSERT(hdr == 0x1f1, "The setup header has the wrong offset!"); | 57 | . = ASSERT(hdr == 0x1f1, "The setup header has the wrong offset!"); |
58 | /* Necessary for the very-old-loader check to work... */ | ||
59 | . = ASSERT(__end_init <= 5*512, "init sections too big!"); | ||
60 | |||
55 | } | 61 | } |
diff --git a/arch/x86/boot/tty.c b/arch/x86/boot/tty.c index 7e8e8b25f5f6..01ec69c901c7 100644 --- a/arch/x86/boot/tty.c +++ b/arch/x86/boot/tty.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * | 2 | * |
3 | * Copyright (C) 1991, 1992 Linus Torvalds | 3 | * Copyright (C) 1991, 1992 Linus Torvalds |
4 | * Copyright 2007 rPath, Inc. - All Rights Reserved | 4 | * Copyright 2007 rPath, Inc. - All Rights Reserved |
5 | * Copyright 2009 Intel Corporation; author H. Peter Anvin | ||
5 | * | 6 | * |
6 | * This file is part of the Linux kernel, and is made available under | 7 | * 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 | * the terms of the GNU General Public License version 2. |
@@ -22,24 +23,23 @@ | |||
22 | 23 | ||
23 | void __attribute__((section(".inittext"))) putchar(int ch) | 24 | void __attribute__((section(".inittext"))) putchar(int ch) |
24 | { | 25 | { |
25 | unsigned char c = ch; | 26 | struct biosregs ireg; |
26 | 27 | ||
27 | if (c == '\n') | 28 | if (ch == '\n') |
28 | putchar('\r'); /* \n -> \r\n */ | 29 | putchar('\r'); /* \n -> \r\n */ |
29 | 30 | ||
30 | /* int $0x10 is known to have bugs involving touching registers | 31 | initregs(&ireg); |
31 | it shouldn't. Be extra conservative... */ | 32 | ireg.bx = 0x0007; |
32 | asm volatile("pushal; pushw %%ds; int $0x10; popw %%ds; popal" | 33 | ireg.cx = 0x0001; |
33 | : : "b" (0x0007), "c" (0x0001), "a" (0x0e00|ch)); | 34 | ireg.ah = 0x0e; |
35 | ireg.al = ch; | ||
36 | intcall(0x10, &ireg, NULL); | ||
34 | } | 37 | } |
35 | 38 | ||
36 | void __attribute__((section(".inittext"))) puts(const char *str) | 39 | void __attribute__((section(".inittext"))) puts(const char *str) |
37 | { | 40 | { |
38 | int n = 0; | 41 | while (*str) |
39 | while (*str) { | ||
40 | putchar(*str++); | 42 | putchar(*str++); |
41 | n++; | ||
42 | } | ||
43 | } | 43 | } |
44 | 44 | ||
45 | /* | 45 | /* |
@@ -49,14 +49,13 @@ void __attribute__((section(".inittext"))) puts(const char *str) | |||
49 | 49 | ||
50 | static u8 gettime(void) | 50 | static u8 gettime(void) |
51 | { | 51 | { |
52 | u16 ax = 0x0200; | 52 | struct biosregs ireg, oreg; |
53 | u16 cx, dx; | ||
54 | 53 | ||
55 | asm volatile("int $0x1a" | 54 | initregs(&ireg); |
56 | : "+a" (ax), "=c" (cx), "=d" (dx) | 55 | ireg.ah = 0x02; |
57 | : : "ebx", "esi", "edi"); | 56 | intcall(0x1a, &ireg, &oreg); |
58 | 57 | ||
59 | return dx >> 8; | 58 | return oreg.dh; |
60 | } | 59 | } |
61 | 60 | ||
62 | /* | 61 | /* |
@@ -64,19 +63,24 @@ static u8 gettime(void) | |||
64 | */ | 63 | */ |
65 | int getchar(void) | 64 | int getchar(void) |
66 | { | 65 | { |
67 | u16 ax = 0; | 66 | struct biosregs ireg, oreg; |
68 | asm volatile("int $0x16" : "+a" (ax)); | 67 | |
68 | initregs(&ireg); | ||
69 | /* ireg.ah = 0x00; */ | ||
70 | intcall(0x16, &ireg, &oreg); | ||
69 | 71 | ||
70 | return ax & 0xff; | 72 | return oreg.al; |
71 | } | 73 | } |
72 | 74 | ||
73 | static int kbd_pending(void) | 75 | static int kbd_pending(void) |
74 | { | 76 | { |
75 | u8 pending; | 77 | struct biosregs ireg, oreg; |
76 | asm volatile("int $0x16; setnz %0" | 78 | |
77 | : "=qm" (pending) | 79 | initregs(&ireg); |
78 | : "a" (0x0100)); | 80 | ireg.ah = 0x01; |
79 | return pending; | 81 | intcall(0x16, &ireg, &oreg); |
82 | |||
83 | return !(oreg.eflags & X86_EFLAGS_ZF); | ||
80 | } | 84 | } |
81 | 85 | ||
82 | void kbd_flush(void) | 86 | void kbd_flush(void) |
diff --git a/arch/x86/boot/video-bios.c b/arch/x86/boot/video-bios.c index 3fa979c9c363..d660be492363 100644 --- a/arch/x86/boot/video-bios.c +++ b/arch/x86/boot/video-bios.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * | 2 | * |
3 | * Copyright (C) 1991, 1992 Linus Torvalds | 3 | * Copyright (C) 1991, 1992 Linus Torvalds |
4 | * Copyright 2007 rPath, Inc. - All Rights Reserved | 4 | * Copyright 2007 rPath, Inc. - All Rights Reserved |
5 | * Copyright 2009 Intel Corporation; author H. Peter Anvin | ||
5 | * | 6 | * |
6 | * This file is part of the Linux kernel, and is made available under | 7 | * 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 | * the terms of the GNU General Public License version 2. |
@@ -29,21 +30,21 @@ static int bios_set_mode(struct mode_info *mi) | |||
29 | 30 | ||
30 | static int set_bios_mode(u8 mode) | 31 | static int set_bios_mode(u8 mode) |
31 | { | 32 | { |
32 | u16 ax; | 33 | struct biosregs ireg, oreg; |
33 | u8 new_mode; | 34 | u8 new_mode; |
34 | 35 | ||
35 | ax = mode; /* AH=0x00 Set Video Mode */ | 36 | initregs(&ireg); |
36 | asm volatile(INT10 | 37 | ireg.al = mode; /* AH=0x00 Set Video Mode */ |
37 | : "+a" (ax) | 38 | intcall(0x10, &ireg, NULL); |
38 | : : "ebx", "ecx", "edx", "esi", "edi"); | ||
39 | 39 | ||
40 | ax = 0x0f00; /* Get Current Video Mode */ | 40 | |
41 | asm volatile(INT10 | 41 | ireg.ah = 0x0f; /* Get Current Video Mode */ |
42 | : "+a" (ax) | 42 | intcall(0x10, &ireg, &oreg); |
43 | : : "ebx", "ecx", "edx", "esi", "edi"); | ||
44 | 43 | ||
45 | do_restore = 1; /* Assume video contents were lost */ | 44 | do_restore = 1; /* Assume video contents were lost */ |
46 | new_mode = ax & 0x7f; /* Not all BIOSes are clean with the top bit */ | 45 | |
46 | /* Not all BIOSes are clean with the top bit */ | ||
47 | new_mode = ireg.al & 0x7f; | ||
47 | 48 | ||
48 | if (new_mode == mode) | 49 | if (new_mode == mode) |
49 | return 0; /* Mode change OK */ | 50 | return 0; /* Mode change OK */ |
@@ -53,10 +54,8 @@ static int set_bios_mode(u8 mode) | |||
53 | /* Mode setting failed, but we didn't end up where we | 54 | /* Mode setting failed, but we didn't end up where we |
54 | started. That's bad. Try to revert to the original | 55 | started. That's bad. Try to revert to the original |
55 | video mode. */ | 56 | video mode. */ |
56 | ax = boot_params.screen_info.orig_video_mode; | 57 | ireg.ax = boot_params.screen_info.orig_video_mode; |
57 | asm volatile(INT10 | 58 | intcall(0x10, &ireg, NULL); |
58 | : "+a" (ax) | ||
59 | : : "ebx", "ecx", "edx", "esi", "edi"); | ||
60 | } | 59 | } |
61 | #endif | 60 | #endif |
62 | return -1; | 61 | return -1; |
diff --git a/arch/x86/boot/video-vesa.c b/arch/x86/boot/video-vesa.c index 4a58c8ce3f69..c700147d6ffb 100644 --- a/arch/x86/boot/video-vesa.c +++ b/arch/x86/boot/video-vesa.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * | 2 | * |
3 | * Copyright (C) 1991, 1992 Linus Torvalds | 3 | * Copyright (C) 1991, 1992 Linus Torvalds |
4 | * Copyright 2007 rPath, Inc. - All Rights Reserved | 4 | * Copyright 2007 rPath, Inc. - All Rights Reserved |
5 | * Copyright 2009 Intel Corporation; author H. Peter Anvin | ||
5 | * | 6 | * |
6 | * This file is part of the Linux kernel, and is made available under | 7 | * 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 | * the terms of the GNU General Public License version 2. |
@@ -31,7 +32,7 @@ static inline void vesa_store_mode_params_graphics(void) {} | |||
31 | static int vesa_probe(void) | 32 | static int vesa_probe(void) |
32 | { | 33 | { |
33 | #if defined(CONFIG_VIDEO_VESA) || defined(CONFIG_FIRMWARE_EDID) | 34 | #if defined(CONFIG_VIDEO_VESA) || defined(CONFIG_FIRMWARE_EDID) |
34 | u16 ax, cx, di; | 35 | struct biosregs ireg, oreg; |
35 | u16 mode; | 36 | u16 mode; |
36 | addr_t mode_ptr; | 37 | addr_t mode_ptr; |
37 | struct mode_info *mi; | 38 | struct mode_info *mi; |
@@ -39,13 +40,12 @@ static int vesa_probe(void) | |||
39 | 40 | ||
40 | video_vesa.modes = GET_HEAP(struct mode_info, 0); | 41 | video_vesa.modes = GET_HEAP(struct mode_info, 0); |
41 | 42 | ||
42 | ax = 0x4f00; | 43 | initregs(&ireg); |
43 | di = (size_t)&vginfo; | 44 | ireg.ax = 0x4f00; |
44 | asm(INT10 | 45 | ireg.di = (size_t)&vginfo; |
45 | : "+a" (ax), "+D" (di), "=m" (vginfo) | 46 | intcall(0x10, &ireg, &oreg); |
46 | : : "ebx", "ecx", "edx", "esi"); | ||
47 | 47 | ||
48 | if (ax != 0x004f || | 48 | if (ireg.ax != 0x004f || |
49 | vginfo.signature != VESA_MAGIC || | 49 | vginfo.signature != VESA_MAGIC || |
50 | vginfo.version < 0x0102) | 50 | vginfo.version < 0x0102) |
51 | return 0; /* Not present */ | 51 | return 0; /* Not present */ |
@@ -65,14 +65,12 @@ static int vesa_probe(void) | |||
65 | 65 | ||
66 | memset(&vminfo, 0, sizeof vminfo); /* Just in case... */ | 66 | memset(&vminfo, 0, sizeof vminfo); /* Just in case... */ |
67 | 67 | ||
68 | ax = 0x4f01; | 68 | ireg.ax = 0x4f01; |
69 | cx = mode; | 69 | ireg.cx = mode; |
70 | di = (size_t)&vminfo; | 70 | ireg.di = (size_t)&vminfo; |
71 | asm(INT10 | 71 | intcall(0x10, &ireg, &oreg); |
72 | : "+a" (ax), "+c" (cx), "+D" (di), "=m" (vminfo) | ||
73 | : : "ebx", "edx", "esi"); | ||
74 | 72 | ||
75 | if (ax != 0x004f) | 73 | if (ireg.ax != 0x004f) |
76 | continue; | 74 | continue; |
77 | 75 | ||
78 | if ((vminfo.mode_attr & 0x15) == 0x05) { | 76 | if ((vminfo.mode_attr & 0x15) == 0x05) { |
@@ -111,20 +109,19 @@ static int vesa_probe(void) | |||
111 | 109 | ||
112 | static int vesa_set_mode(struct mode_info *mode) | 110 | static int vesa_set_mode(struct mode_info *mode) |
113 | { | 111 | { |
114 | u16 ax, bx, cx, di; | 112 | struct biosregs ireg, oreg; |
115 | int is_graphic; | 113 | int is_graphic; |
116 | u16 vesa_mode = mode->mode - VIDEO_FIRST_VESA; | 114 | u16 vesa_mode = mode->mode - VIDEO_FIRST_VESA; |
117 | 115 | ||
118 | memset(&vminfo, 0, sizeof vminfo); /* Just in case... */ | 116 | memset(&vminfo, 0, sizeof vminfo); /* Just in case... */ |
119 | 117 | ||
120 | ax = 0x4f01; | 118 | initregs(&ireg); |
121 | cx = vesa_mode; | 119 | ireg.ax = 0x4f01; |
122 | di = (size_t)&vminfo; | 120 | ireg.cx = vesa_mode; |
123 | asm(INT10 | 121 | ireg.di = (size_t)&vminfo; |
124 | : "+a" (ax), "+c" (cx), "+D" (di), "=m" (vminfo) | 122 | intcall(0x10, &ireg, &oreg); |
125 | : : "ebx", "edx", "esi"); | ||
126 | 123 | ||
127 | if (ax != 0x004f) | 124 | if (oreg.ax != 0x004f) |
128 | return -1; | 125 | return -1; |
129 | 126 | ||
130 | if ((vminfo.mode_attr & 0x15) == 0x05) { | 127 | if ((vminfo.mode_attr & 0x15) == 0x05) { |
@@ -141,14 +138,12 @@ static int vesa_set_mode(struct mode_info *mode) | |||
141 | } | 138 | } |
142 | 139 | ||
143 | 140 | ||
144 | ax = 0x4f02; | 141 | initregs(&ireg); |
145 | bx = vesa_mode; | 142 | ireg.ax = 0x4f02; |
146 | di = 0; | 143 | ireg.bx = vesa_mode; |
147 | asm volatile(INT10 | 144 | intcall(0x10, &ireg, &oreg); |
148 | : "+a" (ax), "+b" (bx), "+D" (di) | ||
149 | : : "ecx", "edx", "esi"); | ||
150 | 145 | ||
151 | if (ax != 0x004f) | 146 | if (oreg.ax != 0x004f) |
152 | return -1; | 147 | return -1; |
153 | 148 | ||
154 | graphic_mode = is_graphic; | 149 | graphic_mode = is_graphic; |
@@ -171,50 +166,45 @@ static int vesa_set_mode(struct mode_info *mode) | |||
171 | /* Switch DAC to 8-bit mode */ | 166 | /* Switch DAC to 8-bit mode */ |
172 | static void vesa_dac_set_8bits(void) | 167 | static void vesa_dac_set_8bits(void) |
173 | { | 168 | { |
169 | struct biosregs ireg, oreg; | ||
174 | u8 dac_size = 6; | 170 | u8 dac_size = 6; |
175 | 171 | ||
176 | /* If possible, switch the DAC to 8-bit mode */ | 172 | /* If possible, switch the DAC to 8-bit mode */ |
177 | if (vginfo.capabilities & 1) { | 173 | if (vginfo.capabilities & 1) { |
178 | u16 ax, bx; | 174 | initregs(&ireg); |
179 | 175 | ireg.ax = 0x4f08; | |
180 | ax = 0x4f08; | 176 | ireg.bh = 0x08; |
181 | bx = 0x0800; | 177 | intcall(0x10, &ireg, &oreg); |
182 | asm volatile(INT10 | 178 | if (oreg.ax == 0x004f) |
183 | : "+a" (ax), "+b" (bx) | 179 | dac_size = oreg.bh; |
184 | : : "ecx", "edx", "esi", "edi"); | ||
185 | |||
186 | if (ax == 0x004f) | ||
187 | dac_size = bx >> 8; | ||
188 | } | 180 | } |
189 | 181 | ||
190 | /* Set the color sizes to the DAC size, and offsets to 0 */ | 182 | /* Set the color sizes to the DAC size, and offsets to 0 */ |
191 | boot_params.screen_info.red_size = dac_size; | 183 | boot_params.screen_info.red_size = dac_size; |
192 | boot_params.screen_info.green_size = dac_size; | 184 | boot_params.screen_info.green_size = dac_size; |
193 | boot_params.screen_info.blue_size = dac_size; | 185 | boot_params.screen_info.blue_size = dac_size; |
194 | boot_params.screen_info.rsvd_size = dac_size; | 186 | boot_params.screen_info.rsvd_size = dac_size; |
195 | 187 | ||
196 | boot_params.screen_info.red_pos = 0; | 188 | boot_params.screen_info.red_pos = 0; |
197 | boot_params.screen_info.green_pos = 0; | 189 | boot_params.screen_info.green_pos = 0; |
198 | boot_params.screen_info.blue_pos = 0; | 190 | boot_params.screen_info.blue_pos = 0; |
199 | boot_params.screen_info.rsvd_pos = 0; | 191 | boot_params.screen_info.rsvd_pos = 0; |
200 | } | 192 | } |
201 | 193 | ||
202 | /* Save the VESA protected mode info */ | 194 | /* Save the VESA protected mode info */ |
203 | static void vesa_store_pm_info(void) | 195 | static void vesa_store_pm_info(void) |
204 | { | 196 | { |
205 | u16 ax, bx, di, es; | 197 | struct biosregs ireg, oreg; |
206 | 198 | ||
207 | ax = 0x4f0a; | 199 | initregs(&ireg); |
208 | bx = di = 0; | 200 | ireg.ax = 0x4f0a; |
209 | asm("pushw %%es; "INT10"; movw %%es,%0; popw %%es" | 201 | intcall(0x10, &ireg, &oreg); |
210 | : "=d" (es), "+a" (ax), "+b" (bx), "+D" (di) | ||
211 | : : "ecx", "esi"); | ||
212 | 202 | ||
213 | if (ax != 0x004f) | 203 | if (oreg.ax != 0x004f) |
214 | return; | 204 | return; |
215 | 205 | ||
216 | boot_params.screen_info.vesapm_seg = es; | 206 | boot_params.screen_info.vesapm_seg = oreg.es; |
217 | boot_params.screen_info.vesapm_off = di; | 207 | boot_params.screen_info.vesapm_off = oreg.di; |
218 | } | 208 | } |
219 | 209 | ||
220 | /* | 210 | /* |
@@ -252,7 +242,7 @@ static void vesa_store_mode_params_graphics(void) | |||
252 | void vesa_store_edid(void) | 242 | void vesa_store_edid(void) |
253 | { | 243 | { |
254 | #ifdef CONFIG_FIRMWARE_EDID | 244 | #ifdef CONFIG_FIRMWARE_EDID |
255 | u16 ax, bx, cx, dx, di; | 245 | struct biosregs ireg, oreg; |
256 | 246 | ||
257 | /* Apparently used as a nonsense token... */ | 247 | /* Apparently used as a nonsense token... */ |
258 | memset(&boot_params.edid_info, 0x13, sizeof boot_params.edid_info); | 248 | memset(&boot_params.edid_info, 0x13, sizeof boot_params.edid_info); |
@@ -260,33 +250,26 @@ void vesa_store_edid(void) | |||
260 | if (vginfo.version < 0x0200) | 250 | if (vginfo.version < 0x0200) |
261 | return; /* EDID requires VBE 2.0+ */ | 251 | return; /* EDID requires VBE 2.0+ */ |
262 | 252 | ||
263 | ax = 0x4f15; /* VBE DDC */ | 253 | initregs(&ireg); |
264 | bx = 0x0000; /* Report DDC capabilities */ | 254 | ireg.ax = 0x4f15; /* VBE DDC */ |
265 | cx = 0; /* Controller 0 */ | 255 | /* ireg.bx = 0x0000; */ /* Report DDC capabilities */ |
266 | di = 0; /* ES:DI must be 0 by spec */ | 256 | /* ireg.cx = 0; */ /* Controller 0 */ |
267 | 257 | ireg.es = 0; /* ES:DI must be 0 by spec */ | |
268 | /* Note: The VBE DDC spec is different from the main VESA spec; | 258 | intcall(0x10, &ireg, &oreg); |
269 | we genuinely have to assume all registers are destroyed here. */ | ||
270 | |||
271 | asm("pushw %%es; movw %2,%%es; "INT10"; popw %%es" | ||
272 | : "+a" (ax), "+b" (bx), "+c" (cx), "+D" (di) | ||
273 | : : "esi", "edx"); | ||
274 | 259 | ||
275 | if (ax != 0x004f) | 260 | if (oreg.ax != 0x004f) |
276 | return; /* No EDID */ | 261 | return; /* No EDID */ |
277 | 262 | ||
278 | /* BH = time in seconds to transfer EDD information */ | 263 | /* BH = time in seconds to transfer EDD information */ |
279 | /* BL = DDC level supported */ | 264 | /* BL = DDC level supported */ |
280 | 265 | ||
281 | ax = 0x4f15; /* VBE DDC */ | 266 | ireg.ax = 0x4f15; /* VBE DDC */ |
282 | bx = 0x0001; /* Read EDID */ | 267 | ireg.bx = 0x0001; /* Read EDID */ |
283 | cx = 0; /* Controller 0 */ | 268 | /* ireg.cx = 0; */ /* Controller 0 */ |
284 | dx = 0; /* EDID block number */ | 269 | /* ireg.dx = 0; */ /* EDID block number */ |
285 | di =(size_t) &boot_params.edid_info; /* (ES:)Pointer to block */ | 270 | ireg.es = ds(); |
286 | asm(INT10 | 271 | ireg.di =(size_t)&boot_params.edid_info; /* (ES:)Pointer to block */ |
287 | : "+a" (ax), "+b" (bx), "+d" (dx), "=m" (boot_params.edid_info), | 272 | intcall(0x10, &ireg, &oreg); |
288 | "+c" (cx), "+D" (di) | ||
289 | : : "esi"); | ||
290 | #endif /* CONFIG_FIRMWARE_EDID */ | 273 | #endif /* CONFIG_FIRMWARE_EDID */ |
291 | } | 274 | } |
292 | 275 | ||
diff --git a/arch/x86/boot/video-vga.c b/arch/x86/boot/video-vga.c index 9e0587a37768..8f8d827e254d 100644 --- a/arch/x86/boot/video-vga.c +++ b/arch/x86/boot/video-vga.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * | 2 | * |
3 | * Copyright (C) 1991, 1992 Linus Torvalds | 3 | * Copyright (C) 1991, 1992 Linus Torvalds |
4 | * Copyright 2007 rPath, Inc. - All Rights Reserved | 4 | * Copyright 2007 rPath, Inc. - All Rights Reserved |
5 | * Copyright 2009 Intel Corporation; author H. Peter Anvin | ||
5 | * | 6 | * |
6 | * This file is part of the Linux kernel, and is made available under | 7 | * 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 | * the terms of the GNU General Public License version 2. |
@@ -39,30 +40,30 @@ static __videocard video_vga; | |||
39 | /* Set basic 80x25 mode */ | 40 | /* Set basic 80x25 mode */ |
40 | static u8 vga_set_basic_mode(void) | 41 | static u8 vga_set_basic_mode(void) |
41 | { | 42 | { |
43 | struct biosregs ireg, oreg; | ||
42 | u16 ax; | 44 | u16 ax; |
43 | u8 rows; | 45 | u8 rows; |
44 | u8 mode; | 46 | u8 mode; |
45 | 47 | ||
48 | initregs(&ireg); | ||
49 | |||
46 | #ifdef CONFIG_VIDEO_400_HACK | 50 | #ifdef CONFIG_VIDEO_400_HACK |
47 | if (adapter >= ADAPTER_VGA) { | 51 | if (adapter >= ADAPTER_VGA) { |
48 | asm volatile(INT10 | 52 | ireg.ax = 0x1202; |
49 | : : "a" (0x1202), "b" (0x0030) | 53 | ireg.bx = 0x0030; |
50 | : "ecx", "edx", "esi", "edi"); | 54 | intcall(0x10, &ireg, NULL); |
51 | } | 55 | } |
52 | #endif | 56 | #endif |
53 | 57 | ||
54 | ax = 0x0f00; | 58 | ax = 0x0f00; |
55 | asm volatile(INT10 | 59 | intcall(0x10, &ireg, &oreg); |
56 | : "+a" (ax) | 60 | mode = oreg.al; |
57 | : : "ebx", "ecx", "edx", "esi", "edi"); | ||
58 | |||
59 | mode = (u8)ax; | ||
60 | 61 | ||
61 | set_fs(0); | 62 | set_fs(0); |
62 | rows = rdfs8(0x484); /* rows minus one */ | 63 | rows = rdfs8(0x484); /* rows minus one */ |
63 | 64 | ||
64 | #ifndef CONFIG_VIDEO_400_HACK | 65 | #ifndef CONFIG_VIDEO_400_HACK |
65 | if ((ax == 0x5003 || ax == 0x5007) && | 66 | if ((oreg.ax == 0x5003 || oreg.ax == 0x5007) && |
66 | (rows == 0 || rows == 24)) | 67 | (rows == 0 || rows == 24)) |
67 | return mode; | 68 | return mode; |
68 | #endif | 69 | #endif |
@@ -71,10 +72,8 @@ static u8 vga_set_basic_mode(void) | |||
71 | mode = 3; | 72 | mode = 3; |
72 | 73 | ||
73 | /* Set the mode */ | 74 | /* Set the mode */ |
74 | ax = mode; | 75 | ireg.ax = mode; /* AH=0: set mode */ |
75 | asm volatile(INT10 | 76 | intcall(0x10, &ireg, NULL); |
76 | : "+a" (ax) | ||
77 | : : "ebx", "ecx", "edx", "esi", "edi"); | ||
78 | do_restore = 1; | 77 | do_restore = 1; |
79 | return mode; | 78 | return mode; |
80 | } | 79 | } |
@@ -82,43 +81,69 @@ static u8 vga_set_basic_mode(void) | |||
82 | static void vga_set_8font(void) | 81 | static void vga_set_8font(void) |
83 | { | 82 | { |
84 | /* Set 8x8 font - 80x43 on EGA, 80x50 on VGA */ | 83 | /* Set 8x8 font - 80x43 on EGA, 80x50 on VGA */ |
84 | struct biosregs ireg; | ||
85 | |||
86 | initregs(&ireg); | ||
85 | 87 | ||
86 | /* Set 8x8 font */ | 88 | /* Set 8x8 font */ |
87 | asm volatile(INT10 : : "a" (0x1112), "b" (0)); | 89 | ireg.ax = 0x1112; |
90 | /* ireg.bl = 0; */ | ||
91 | intcall(0x10, &ireg, NULL); | ||
88 | 92 | ||
89 | /* Use alternate print screen */ | 93 | /* Use alternate print screen */ |
90 | asm volatile(INT10 : : "a" (0x1200), "b" (0x20)); | 94 | ireg.ax = 0x1200; |
95 | ireg.bl = 0x20; | ||
96 | intcall(0x10, &ireg, NULL); | ||
91 | 97 | ||
92 | /* Turn off cursor emulation */ | 98 | /* Turn off cursor emulation */ |
93 | asm volatile(INT10 : : "a" (0x1201), "b" (0x34)); | 99 | ireg.ax = 0x1201; |
100 | ireg.bl = 0x34; | ||
101 | intcall(0x10, &ireg, NULL); | ||
94 | 102 | ||
95 | /* Cursor is scan lines 6-7 */ | 103 | /* Cursor is scan lines 6-7 */ |
96 | asm volatile(INT10 : : "a" (0x0100), "c" (0x0607)); | 104 | ireg.ax = 0x0100; |
105 | ireg.cx = 0x0607; | ||
106 | intcall(0x10, &ireg, NULL); | ||
97 | } | 107 | } |
98 | 108 | ||
99 | static void vga_set_14font(void) | 109 | static void vga_set_14font(void) |
100 | { | 110 | { |
101 | /* Set 9x14 font - 80x28 on VGA */ | 111 | /* Set 9x14 font - 80x28 on VGA */ |
112 | struct biosregs ireg; | ||
113 | |||
114 | initregs(&ireg); | ||
102 | 115 | ||
103 | /* Set 9x14 font */ | 116 | /* Set 9x14 font */ |
104 | asm volatile(INT10 : : "a" (0x1111), "b" (0)); | 117 | ireg.ax = 0x1111; |
118 | /* ireg.bl = 0; */ | ||
119 | intcall(0x10, &ireg, NULL); | ||
105 | 120 | ||
106 | /* Turn off cursor emulation */ | 121 | /* Turn off cursor emulation */ |
107 | asm volatile(INT10 : : "a" (0x1201), "b" (0x34)); | 122 | ireg.ax = 0x1201; |
123 | ireg.bl = 0x34; | ||
124 | intcall(0x10, &ireg, NULL); | ||
108 | 125 | ||
109 | /* Cursor is scan lines 11-12 */ | 126 | /* Cursor is scan lines 11-12 */ |
110 | asm volatile(INT10 : : "a" (0x0100), "c" (0x0b0c)); | 127 | ireg.ax = 0x0100; |
128 | ireg.cx = 0x0b0c; | ||
129 | intcall(0x10, &ireg, NULL); | ||
111 | } | 130 | } |
112 | 131 | ||
113 | static void vga_set_80x43(void) | 132 | static void vga_set_80x43(void) |
114 | { | 133 | { |
115 | /* Set 80x43 mode on VGA (not EGA) */ | 134 | /* Set 80x43 mode on VGA (not EGA) */ |
135 | struct biosregs ireg; | ||
136 | |||
137 | initregs(&ireg); | ||
116 | 138 | ||
117 | /* Set 350 scans */ | 139 | /* Set 350 scans */ |
118 | asm volatile(INT10 : : "a" (0x1201), "b" (0x30)); | 140 | ireg.ax = 0x1201; |
141 | ireg.bl = 0x30; | ||
142 | intcall(0x10, &ireg, NULL); | ||
119 | 143 | ||
120 | /* Reset video mode */ | 144 | /* Reset video mode */ |
121 | asm volatile(INT10 : : "a" (0x0003)); | 145 | ireg.ax = 0x0003; |
146 | intcall(0x10, &ireg, NULL); | ||
122 | 147 | ||
123 | vga_set_8font(); | 148 | vga_set_8font(); |
124 | } | 149 | } |
@@ -225,8 +250,6 @@ static int vga_set_mode(struct mode_info *mode) | |||
225 | */ | 250 | */ |
226 | static int vga_probe(void) | 251 | static int vga_probe(void) |
227 | { | 252 | { |
228 | u16 ega_bx; | ||
229 | |||
230 | static const char *card_name[] = { | 253 | static const char *card_name[] = { |
231 | "CGA/MDA/HGC", "EGA", "VGA" | 254 | "CGA/MDA/HGC", "EGA", "VGA" |
232 | }; | 255 | }; |
@@ -240,26 +263,26 @@ static int vga_probe(void) | |||
240 | sizeof(ega_modes)/sizeof(struct mode_info), | 263 | sizeof(ega_modes)/sizeof(struct mode_info), |
241 | sizeof(vga_modes)/sizeof(struct mode_info), | 264 | sizeof(vga_modes)/sizeof(struct mode_info), |
242 | }; | 265 | }; |
243 | u8 vga_flag; | ||
244 | 266 | ||
245 | asm(INT10 | 267 | struct biosregs ireg, oreg; |
246 | : "=b" (ega_bx) | 268 | |
247 | : "a" (0x1200), "b" (0x10) /* Check EGA/VGA */ | 269 | initregs(&ireg); |
248 | : "ecx", "edx", "esi", "edi"); | 270 | |
271 | ireg.ax = 0x1200; | ||
272 | ireg.bl = 0x10; /* Check EGA/VGA */ | ||
273 | intcall(0x10, &ireg, &oreg); | ||
249 | 274 | ||
250 | #ifndef _WAKEUP | 275 | #ifndef _WAKEUP |
251 | boot_params.screen_info.orig_video_ega_bx = ega_bx; | 276 | boot_params.screen_info.orig_video_ega_bx = oreg.bx; |
252 | #endif | 277 | #endif |
253 | 278 | ||
254 | /* If we have MDA/CGA/HGC then BL will be unchanged at 0x10 */ | 279 | /* If we have MDA/CGA/HGC then BL will be unchanged at 0x10 */ |
255 | if ((u8)ega_bx != 0x10) { | 280 | if (oreg.bl != 0x10) { |
256 | /* EGA/VGA */ | 281 | /* EGA/VGA */ |
257 | asm(INT10 | 282 | ireg.ax = 0x1a00; |
258 | : "=a" (vga_flag) | 283 | intcall(0x10, &ireg, &oreg); |
259 | : "a" (0x1a00) | ||
260 | : "ebx", "ecx", "edx", "esi", "edi"); | ||
261 | 284 | ||
262 | if (vga_flag == 0x1a) { | 285 | if (oreg.al == 0x1a) { |
263 | adapter = ADAPTER_VGA; | 286 | adapter = ADAPTER_VGA; |
264 | #ifndef _WAKEUP | 287 | #ifndef _WAKEUP |
265 | boot_params.screen_info.orig_video_isVGA = 1; | 288 | boot_params.screen_info.orig_video_isVGA = 1; |
diff --git a/arch/x86/boot/video.c b/arch/x86/boot/video.c index 3bef2c1febe9..bad728b76fc2 100644 --- a/arch/x86/boot/video.c +++ b/arch/x86/boot/video.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * | 2 | * |
3 | * Copyright (C) 1991, 1992 Linus Torvalds | 3 | * Copyright (C) 1991, 1992 Linus Torvalds |
4 | * Copyright 2007 rPath, Inc. - All Rights Reserved | 4 | * Copyright 2007 rPath, Inc. - All Rights Reserved |
5 | * Copyright 2009 Intel Corporation; author H. Peter Anvin | ||
5 | * | 6 | * |
6 | * This file is part of the Linux kernel, and is made available under | 7 | * 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 | * the terms of the GNU General Public License version 2. |
@@ -18,33 +19,29 @@ | |||
18 | 19 | ||
19 | static void store_cursor_position(void) | 20 | static void store_cursor_position(void) |
20 | { | 21 | { |
21 | u16 curpos; | 22 | struct biosregs ireg, oreg; |
22 | u16 ax, bx; | ||
23 | 23 | ||
24 | ax = 0x0300; | 24 | initregs(&ireg); |
25 | bx = 0; | 25 | ireg.ah = 0x03; |
26 | asm(INT10 | 26 | intcall(0x10, &ireg, &oreg); |
27 | : "=d" (curpos), "+a" (ax), "+b" (bx) | ||
28 | : : "ecx", "esi", "edi"); | ||
29 | 27 | ||
30 | boot_params.screen_info.orig_x = curpos; | 28 | boot_params.screen_info.orig_x = oreg.dl; |
31 | boot_params.screen_info.orig_y = curpos >> 8; | 29 | boot_params.screen_info.orig_y = oreg.dh; |
32 | } | 30 | } |
33 | 31 | ||
34 | static void store_video_mode(void) | 32 | static void store_video_mode(void) |
35 | { | 33 | { |
36 | u16 ax, page; | 34 | struct biosregs ireg, oreg; |
37 | 35 | ||
38 | /* N.B.: the saving of the video page here is a bit silly, | 36 | /* N.B.: the saving of the video page here is a bit silly, |
39 | since we pretty much assume page 0 everywhere. */ | 37 | since we pretty much assume page 0 everywhere. */ |
40 | ax = 0x0f00; | 38 | initregs(&ireg); |
41 | asm(INT10 | 39 | ireg.ah = 0x0f; |
42 | : "+a" (ax), "=b" (page) | 40 | intcall(0x10, &ireg, &oreg); |
43 | : : "ecx", "edx", "esi", "edi"); | ||
44 | 41 | ||
45 | /* Not all BIOSes are clean with respect to the top bit */ | 42 | /* Not all BIOSes are clean with respect to the top bit */ |
46 | boot_params.screen_info.orig_video_mode = ax & 0x7f; | 43 | boot_params.screen_info.orig_video_mode = oreg.al & 0x7f; |
47 | boot_params.screen_info.orig_video_page = page >> 8; | 44 | boot_params.screen_info.orig_video_page = oreg.bh; |
48 | } | 45 | } |
49 | 46 | ||
50 | /* | 47 | /* |
@@ -257,7 +254,7 @@ static void restore_screen(void) | |||
257 | int y; | 254 | int y; |
258 | addr_t dst = 0; | 255 | addr_t dst = 0; |
259 | u16 *src = saved.data; | 256 | u16 *src = saved.data; |
260 | u16 ax, bx, dx; | 257 | struct biosregs ireg; |
261 | 258 | ||
262 | if (graphic_mode) | 259 | if (graphic_mode) |
263 | return; /* Can't restore onto a graphic mode */ | 260 | return; /* Can't restore onto a graphic mode */ |
@@ -296,12 +293,11 @@ static void restore_screen(void) | |||
296 | } | 293 | } |
297 | 294 | ||
298 | /* Restore cursor position */ | 295 | /* Restore cursor position */ |
299 | ax = 0x0200; /* Set cursor position */ | 296 | initregs(&ireg); |
300 | bx = 0; /* Page number (<< 8) */ | 297 | ireg.ah = 0x02; /* Set cursor position */ |
301 | dx = (saved.cury << 8)+saved.curx; | 298 | ireg.dh = saved.cury; |
302 | asm volatile(INT10 | 299 | ireg.dl = saved.curx; |
303 | : "+a" (ax), "+b" (bx), "+d" (dx) | 300 | intcall(0x10, &ireg, NULL); |
304 | : : "ecx", "esi", "edi"); | ||
305 | } | 301 | } |
306 | #else | 302 | #else |
307 | #define save_screen() ((void)0) | 303 | #define save_screen() ((void)0) |
diff --git a/arch/x86/boot/video.h b/arch/x86/boot/video.h index ee63f5d14461..5bb174a997fc 100644 --- a/arch/x86/boot/video.h +++ b/arch/x86/boot/video.h | |||
@@ -112,20 +112,6 @@ extern int force_x, force_y; /* Don't query the BIOS for cols/rows */ | |||
112 | extern int do_restore; /* Restore screen contents */ | 112 | extern int do_restore; /* Restore screen contents */ |
113 | extern int graphic_mode; /* Graphics mode with linear frame buffer */ | 113 | extern int graphic_mode; /* Graphics mode with linear frame buffer */ |
114 | 114 | ||
115 | /* | ||
116 | * int $0x10 is notorious for touching registers it shouldn't. | ||
117 | * gcc doesn't like %ebp being clobbered, so define it as a push/pop | ||
118 | * sequence here. | ||
119 | * | ||
120 | * A number of systems, including the original PC can clobber %bp in | ||
121 | * certain circumstances, like when scrolling. There exists at least | ||
122 | * one Trident video card which could clobber DS under a set of | ||
123 | * circumstances that we are unlikely to encounter (scrolling when | ||
124 | * using an extended graphics mode of more than 800x600 pixels), but | ||
125 | * it's cheap insurance to deal with that here. | ||
126 | */ | ||
127 | #define INT10 "pushl %%ebp; pushw %%ds; int $0x10; popw %%ds; popl %%ebp" | ||
128 | |||
129 | /* Accessing VGA indexed registers */ | 115 | /* Accessing VGA indexed registers */ |
130 | static inline u8 in_idx(u16 port, u8 index) | 116 | static inline u8 in_idx(u16 port, u8 index) |
131 | { | 117 | { |
diff --git a/arch/x86/kernel/acpi/realmode/Makefile b/arch/x86/kernel/acpi/realmode/Makefile index 1c31cc0e9def..167bc16ce0e5 100644 --- a/arch/x86/kernel/acpi/realmode/Makefile +++ b/arch/x86/kernel/acpi/realmode/Makefile | |||
@@ -9,7 +9,7 @@ | |||
9 | always := wakeup.bin | 9 | always := wakeup.bin |
10 | targets := wakeup.elf wakeup.lds | 10 | targets := wakeup.elf wakeup.lds |
11 | 11 | ||
12 | wakeup-y += wakeup.o wakemain.o video-mode.o copy.o | 12 | wakeup-y += wakeup.o wakemain.o video-mode.o copy.o bioscall.o regs.o |
13 | 13 | ||
14 | # The link order of the video-*.o modules can matter. In particular, | 14 | # The link order of the video-*.o modules can matter. In particular, |
15 | # video-vga.o *must* be listed first, followed by video-vesa.o. | 15 | # video-vga.o *must* be listed first, followed by video-vesa.o. |
diff --git a/arch/x86/kernel/acpi/realmode/bioscall.S b/arch/x86/kernel/acpi/realmode/bioscall.S new file mode 100644 index 000000000000..f51eb0bb56ce --- /dev/null +++ b/arch/x86/kernel/acpi/realmode/bioscall.S | |||
@@ -0,0 +1 @@ | |||
#include "../../../boot/bioscall.S" | |||
diff --git a/arch/x86/kernel/acpi/realmode/regs.c b/arch/x86/kernel/acpi/realmode/regs.c new file mode 100644 index 000000000000..6206033ba202 --- /dev/null +++ b/arch/x86/kernel/acpi/realmode/regs.c | |||
@@ -0,0 +1 @@ | |||
#include "../../../boot/regs.c" | |||