apm.c 2.3 KB

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