diff options
author | H. Peter Anvin <hpa@zytor.com> | 2007-07-11 15:18:43 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-12 13:55:55 -0400 |
commit | 49df18fa3f95a5c988b64e4e20e15372282e96ea (patch) | |
tree | 4311f0a15c30db6b8e7c804ecff2e1ae0628840d /arch/i386/boot/apm.c | |
parent | 5a8a8128bc218ebd067c660912d838344b05c608 (diff) |
APM probing code
APM probing code for the new x86 setup code. This implements the
same functionality as the assembly version.
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/i386/boot/apm.c')
-rw-r--r-- | arch/i386/boot/apm.c | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/arch/i386/boot/apm.c b/arch/i386/boot/apm.c new file mode 100644 index 000000000000..a34087c370c0 --- /dev/null +++ b/arch/i386/boot/apm.c | |||
@@ -0,0 +1,97 @@ | |||
1 | /* -*- linux-c -*- ------------------------------------------------------- * | ||
2 | * | ||
3 | * Copyright (C) 1991, 1992 Linus Torvalds | ||
4 | * Copyright 2007 rPath, Inc. - All Rights Reserved | ||
5 | * | ||
6 | * Original APM BIOS checking by Stephen Rothwell, May 1994 | ||
7 | * (sfr@canb.auug.org.au) | ||
8 | * | ||
9 | * This file is part of the Linux kernel, and is made available under | ||
10 | * the terms of the GNU General Public License version 2. | ||
11 | * | ||
12 | * ----------------------------------------------------------------------- */ | ||
13 | |||
14 | /* | ||
15 | * arch/i386/boot/apm.c | ||
16 | * | ||
17 | * Get APM BIOS information | ||
18 | */ | ||
19 | |||
20 | #include "boot.h" | ||
21 | |||
22 | #if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE) | ||
23 | |||
24 | int query_apm_bios(void) | ||
25 | { | ||
26 | u16 ax, bx, cx, dx, di; | ||
27 | u32 ebx, esi; | ||
28 | u8 err; | ||
29 | |||
30 | /* APM BIOS installation check */ | ||
31 | ax = 0x5300; | ||
32 | bx = cx = 0; | ||
33 | asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp ; setc %0" | ||
34 | : "=d" (err), "+a" (ax), "+b" (bx), "+c" (cx) | ||
35 | : : "esi", "edi"); | ||
36 | |||
37 | if (err) | ||
38 | return -1; /* No APM BIOS */ | ||
39 | |||
40 | if (bx != 0x504d) /* "PM" signature */ | ||
41 | return -1; | ||
42 | |||
43 | if (cx & 0x02) /* 32 bits supported? */ | ||
44 | return -1; | ||
45 | |||
46 | /* Disconnect first, just in case */ | ||
47 | ax = 0x5304; | ||
48 | asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp" | ||
49 | : "+a" (ax) | ||
50 | : : "ebx", "ecx", "edx", "esi", "edi"); | ||
51 | |||
52 | /* Paranoia */ | ||
53 | ebx = esi = 0; | ||
54 | cx = dx = di = 0; | ||
55 | |||
56 | /* 32-bit connect */ | ||
57 | asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp ; setc %6" | ||
58 | : "=a" (ax), "+b" (ebx), "+c" (cx), "+d" (dx), | ||
59 | "+S" (esi), "+D" (di), "=m" (err) | ||
60 | : "a" (0x5303)); | ||
61 | |||
62 | boot_params.apm_bios_info.cseg = ax; | ||
63 | boot_params.apm_bios_info.offset = ebx; | ||
64 | boot_params.apm_bios_info.cseg_16 = cx; | ||
65 | boot_params.apm_bios_info.dseg = dx; | ||
66 | boot_params.apm_bios_info.cseg_len = (u16)esi; | ||
67 | boot_params.apm_bios_info.cseg_16_len = esi >> 16; | ||
68 | boot_params.apm_bios_info.dseg_len = di; | ||
69 | |||
70 | if (err) | ||
71 | return -1; | ||
72 | |||
73 | /* Redo the installation check as the 32-bit connect; | ||
74 | some BIOSes return different flags this way... */ | ||
75 | |||
76 | ax = 0x5300; | ||
77 | bx = cx = 0; | ||
78 | asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp ; setc %0" | ||
79 | : "=d" (err), "+a" (ax), "+b" (bx), "+c" (cx) | ||
80 | : : "esi", "edi"); | ||
81 | |||
82 | if (err || bx != 0x504d) { | ||
83 | /* Failure with 32-bit connect, try to disconect and ignore */ | ||
84 | ax = 0x5304; | ||
85 | bx = 0; | ||
86 | asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp" | ||
87 | : "+a" (ax), "+b" (bx) | ||
88 | : : "ecx", "edx", "esi", "edi"); | ||
89 | return -1; | ||
90 | } | ||
91 | |||
92 | boot_params.apm_bios_info.version = ax; | ||
93 | boot_params.apm_bios_info.flags = cx; | ||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | #endif | ||