Commit | Line | Data |
---|---|---|
449f2ab9 PA |
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 | } |