| /* -*- linux-c -*- ------------------------------------------------------- * |
| * |
| * Copyright (C) 1991, 1992 Linus Torvalds |
| * Copyright 2007 rPath, Inc. - All Rights Reserved |
| * |
| * Original APM BIOS checking by Stephen Rothwell, May 1994 |
| * (sfr@canb.auug.org.au) |
| * |
| * This file is part of the Linux kernel, and is made available under |
| * the terms of the GNU General Public License version 2. |
| * |
| * ----------------------------------------------------------------------- */ |
| |
| /* |
| * arch/i386/boot/apm.c |
| * |
| * Get APM BIOS information |
| */ |
| |
| #include "boot.h" |
| |
| #if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE) |
| |
| int query_apm_bios(void) |
| { |
| u16 ax, bx, cx, dx, di; |
| u32 ebx, esi; |
| u8 err; |
| |
| /* APM BIOS installation check */ |
| ax = 0x5300; |
| bx = cx = 0; |
| asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp ; setc %0" |
| : "=d" (err), "+a" (ax), "+b" (bx), "+c" (cx) |
| : : "esi", "edi"); |
| |
| if (err) |
| return -1; /* No APM BIOS */ |
| |
| if (bx != 0x504d) /* "PM" signature */ |
| return -1; |
| |
| if (cx & 0x02) /* 32 bits supported? */ |
| return -1; |
| |
| /* Disconnect first, just in case */ |
| ax = 0x5304; |
| asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp" |
| : "+a" (ax) |
| : : "ebx", "ecx", "edx", "esi", "edi"); |
| |
| /* Paranoia */ |
| ebx = esi = 0; |
| cx = dx = di = 0; |
| |
| /* 32-bit connect */ |
| asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp ; setc %6" |
| : "=a" (ax), "+b" (ebx), "+c" (cx), "+d" (dx), |
| "+S" (esi), "+D" (di), "=m" (err) |
| : "a" (0x5303)); |
| |
| boot_params.apm_bios_info.cseg = ax; |
| boot_params.apm_bios_info.offset = ebx; |
| boot_params.apm_bios_info.cseg_16 = cx; |
| boot_params.apm_bios_info.dseg = dx; |
| boot_params.apm_bios_info.cseg_len = (u16)esi; |
| boot_params.apm_bios_info.cseg_16_len = esi >> 16; |
| boot_params.apm_bios_info.dseg_len = di; |
| |
| if (err) |
| return -1; |
| |
| /* Redo the installation check as the 32-bit connect; |
| some BIOSes return different flags this way... */ |
| |
| ax = 0x5300; |
| bx = cx = 0; |
| asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp ; setc %0" |
| : "=d" (err), "+a" (ax), "+b" (bx), "+c" (cx) |
| : : "esi", "edi"); |
| |
| if (err || bx != 0x504d) { |
| /* Failure with 32-bit connect, try to disconect and ignore */ |
| ax = 0x5304; |
| bx = 0; |
| asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp" |
| : "+a" (ax), "+b" (bx) |
| : : "ecx", "edx", "esi", "edi"); |
| return -1; |
| } |
| |
| boot_params.apm_bios_info.version = ax; |
| boot_params.apm_bios_info.flags = cx; |
| return 0; |
| } |
| |
| #endif |