memory.c 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. /* -*- linux-c -*- ------------------------------------------------------- *
  2. *
  3. * Copyright (C) 1991, 1992 Linus Torvalds
  4. * Copyright 2007 rPath, Inc. - All Rights Reserved
  5. *
  6. * This file is part of the Linux kernel, and is made available under
  7. * the terms of the GNU General Public License version 2.
  8. *
  9. * ----------------------------------------------------------------------- */
  10. /*
  11. * arch/i386/boot/memory.c
  12. *
  13. * Memory detection code
  14. */
  15. #include "boot.h"
  16. #define SMAP 0x534d4150 /* ASCII "SMAP" */
  17. static int detect_memory_e820(void)
  18. {
  19. u32 next = 0;
  20. u32 size, id;
  21. u8 err;
  22. struct e820entry *desc = boot_params.e820_map;
  23. do {
  24. size = sizeof(struct e820entry);
  25. id = SMAP;
  26. asm("int $0x15; setc %0"
  27. : "=am" (err), "+b" (next), "+d" (id), "+c" (size),
  28. "=m" (*desc)
  29. : "D" (desc), "a" (0xe820));
  30. if (err || id != SMAP)
  31. break;
  32. boot_params.e820_entries++;
  33. desc++;
  34. } while (next && boot_params.e820_entries < E820MAX);
  35. return boot_params.e820_entries;
  36. }
  37. static int detect_memory_e801(void)
  38. {
  39. u16 ax, bx, cx, dx;
  40. u8 err;
  41. bx = cx = dx = 0;
  42. ax = 0xe801;
  43. asm("stc; int $0x15; setc %0"
  44. : "=m" (err), "+a" (ax), "+b" (bx), "+c" (cx), "+d" (dx));
  45. if (err)
  46. return -1;
  47. /* Do we really need to do this? */
  48. if (cx || dx) {
  49. ax = cx;
  50. bx = dx;
  51. }
  52. if (ax > 15*1024)
  53. return -1; /* Bogus! */
  54. /* This ignores memory above 16MB if we have a memory hole
  55. there. If someone actually finds a machine with a memory
  56. hole at 16MB and no support for 0E820h they should probably
  57. generate a fake e820 map. */
  58. boot_params.alt_mem_k = (ax == 15*1024) ? (dx << 6)+ax : ax;
  59. return 0;
  60. }
  61. static int detect_memory_88(void)
  62. {
  63. u16 ax;
  64. u8 err;
  65. ax = 0x8800;
  66. asm("stc; int $0x15; setc %0" : "=bcdm" (err), "+a" (ax));
  67. boot_params.screen_info.ext_mem_k = ax;
  68. return -err;
  69. }
  70. int detect_memory(void)
  71. {
  72. if (detect_memory_e820() > 0)
  73. return 0;
  74. if (!detect_memory_e801())
  75. return 0;
  76. return detect_memory_88();
  77. }