Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6
[linux-2.6] / arch / i386 / boot / memory.c
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 /*
12  * arch/i386/boot/memory.c
13  *
14  * Memory detection code
15  */
16
17 #include "boot.h"
18
19 #define SMAP    0x534d4150      /* ASCII "SMAP" */
20
21 static int detect_memory_e820(void)
22 {
23         u32 next = 0;
24         u32 size, id;
25         u8 err;
26         struct e820entry *desc = boot_params.e820_map;
27
28         do {
29                 size = sizeof(struct e820entry);
30                 id = SMAP;
31                 asm("int $0x15; setc %0"
32                     : "=am" (err), "+b" (next), "+d" (id), "+c" (size),
33                       "=m" (*desc)
34                     : "D" (desc), "a" (0xe820));
35
36                 if (err || id != SMAP)
37                         break;
38
39                 boot_params.e820_entries++;
40                 desc++;
41         } while (next && boot_params.e820_entries < E820MAX);
42
43         return boot_params.e820_entries;
44 }
45
46 static int detect_memory_e801(void)
47 {
48         u16 ax, bx, cx, dx;
49         u8 err;
50
51         bx = cx = dx = 0;
52         ax = 0xe801;
53         asm("stc; int $0x15; setc %0"
54             : "=m" (err), "+a" (ax), "+b" (bx), "+c" (cx), "+d" (dx));
55
56         if (err)
57                 return -1;
58
59         /* Do we really need to do this? */
60         if (cx || dx) {
61                 ax = cx;
62                 bx = dx;
63         }
64
65         if (ax > 15*1024)
66                 return -1;      /* Bogus! */
67
68         /* This ignores memory above 16MB if we have a memory hole
69            there.  If someone actually finds a machine with a memory
70            hole at 16MB and no support for 0E820h they should probably
71            generate a fake e820 map. */
72         boot_params.alt_mem_k = (ax == 15*1024) ? (dx << 6)+ax : ax;
73
74         return 0;
75 }
76
77 static int detect_memory_88(void)
78 {
79         u16 ax;
80         u8 err;
81
82         ax = 0x8800;
83         asm("stc; int $0x15; setc %0" : "=bcdm" (err), "+a" (ax));
84
85         boot_params.screen_info.ext_mem_k = ax;
86
87         return -err;
88 }
89
90 int detect_memory(void)
91 {
92         if (detect_memory_e820() > 0)
93                 return 0;
94
95         if (!detect_memory_e801())
96                 return 0;
97
98         return detect_memory_88();
99 }