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 * Get APM BIOS information 16 */ 17 18 #include "boot.h" 19 20 int query_apm_bios(void) 21 { 22 u16 ax, bx, cx, dx, di; 23 u32 ebx, esi; 24 u8 err; 25 26 /* APM BIOS installation check */ 27 ax = 0x5300; 28 bx = cx = 0; 29 asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp ; setc %0" 30 : "=d" (err), "+a" (ax), "+b" (bx), "+c" (cx) 31 : : "esi", "edi"); 32 33 if (err) 34 return -1; /* No APM BIOS */ 35 36 if (bx != 0x504d) /* "PM" signature */ 37 return -1; 38 39 if (!(cx & 0x02)) /* 32 bits supported? */ 40 return -1; 41 42 /* Disconnect first, just in case */ 43 ax = 0x5304; 44 bx = 0; 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 53 /* 32-bit connect */ 54 asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp ; setc %6" 55 : "=a" (ax), "+b" (ebx), "+c" (cx), "+d" (dx), 56 "+S" (esi), "+D" (di), "=m" (err) 57 : "a" (0x5303)); 58 59 boot_params.apm_bios_info.cseg = ax; 60 boot_params.apm_bios_info.offset = ebx; 61 boot_params.apm_bios_info.cseg_16 = cx; 62 boot_params.apm_bios_info.dseg = dx; 63 boot_params.apm_bios_info.cseg_len = (u16)esi; 64 boot_params.apm_bios_info.cseg_16_len = esi >> 16; 65 boot_params.apm_bios_info.dseg_len = di; 66 67 if (err) 68 return -1; 69 70 /* Redo the installation check as the 32-bit connect; 71 some BIOSes return different flags this way... */ 72 73 ax = 0x5300; 74 bx = cx = 0; 75 asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp ; setc %0" 76 : "=d" (err), "+a" (ax), "+b" (bx), "+c" (cx) 77 : : "esi", "edi"); 78 79 if (err || bx != 0x504d) { 80 /* Failure with 32-bit connect, try to disconect and ignore */ 81 ax = 0x5304; 82 bx = 0; 83 asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp" 84 : "+a" (ax), "+b" (bx) 85 : : "ecx", "edx", "esi", "edi"); 86 return -1; 87 } 88 89 boot_params.apm_bios_info.version = ax; 90 boot_params.apm_bios_info.flags = cx; 91 return 0; 92 } 93 94