Commit | Line | Data |
---|---|---|
49df18fa PA |
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 | ||
1514ab09 | 43 | if (!(cx & 0x02)) /* 32 bits supported? */ |
49df18fa PA |
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 |