aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorValdimir Serbinenko <phcoder@gmail.com>2010-05-03 16:21:52 +0000
committerStefan Reinauer <stepan@openbios.org>2010-05-03 16:21:52 +0000
commit7339f36961917814ed12d5a4e6f1fe19418b8aca (patch)
tree35da7a81bce4445496e77897efd7277995b6e88f
parent80d9804ff776c677932937ac3faf494acf378b45 (diff)
Qemu, despite "emulating" an intel chipset, uses the CMOS to
tell the BIOS how much RAM the virtual machine has available. This patch fixes the detection. Signed-off-by: Valdimir Serbinenko <phcoder@gmail.com> Acked-by: Stefan Reinauer <stepan@coresystems.de> git-svn-id: svn://svn.coreboot.org/coreboot/trunk@5521 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
-rw-r--r--src/mainboard/emulation/qemu-x86/northbridge.c82
1 files changed, 33 insertions, 49 deletions
diff --git a/src/mainboard/emulation/qemu-x86/northbridge.c b/src/mainboard/emulation/qemu-x86/northbridge.c
index 4260d0c954..7b84928883 100644
--- a/src/mainboard/emulation/qemu-x86/northbridge.c
+++ b/src/mainboard/emulation/qemu-x86/northbridge.c
@@ -53,60 +53,44 @@ static uint32_t find_pci_tolm(struct bus *bus)
extern uint64_t high_tables_base, high_tables_size;
#endif
+#define CMOS_ADDR_PORT 0x70
+#define CMOS_DATA_PORT 0x71
+#define HIGH_RAM_ADDR 0x35
+#define LOW_RAM_ADDR 0x34
+
static void cpu_pci_domain_set_resources(device_t dev)
{
- static const uint8_t ramregs[] = {
- 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x56, 0x57
- };
- device_t mc_dev;
- uint32_t pci_tolm;
-
- pci_tolm = find_pci_tolm(&dev->link[0]);
- mc_dev = dev->link[0].children;
- if (mc_dev) {
- unsigned long tomk, tolmk;
- unsigned char rambits;
- int i, idx;
-
- for(rambits = 0, i = 0; i < ARRAY_SIZE(ramregs); i++) {
- unsigned char reg;
- reg = pci_read_config8(mc_dev, ramregs[i]);
- /* these are ENDING addresses, not sizes.
- * if there is memory in this slot, then reg will be > rambits.
- * So we just take the max, that gives us total.
- * We take the highest one to cover for once and future coreboot
- * bugs. We warn about bugs.
- */
- if (reg > rambits)
- rambits = reg;
- if (reg < rambits)
- printk(BIOS_ERR, "ERROR! register 0x%x is not set!\n",
- ramregs[i]);
- }
- if (rambits == 0) {
- printk(BIOS_ERR, "RAM size config registers are empty; defaulting to 64 MBytes\n");
- rambits = 8;
- }
- printk(BIOS_DEBUG, "I would set ram size to 0x%x Kbytes\n", (rambits)*8*1024);
- tomk = rambits*8*1024;
- /* Compute the top of Low memory */
- tolmk = pci_tolm >> 10;
- if (tolmk >= tomk) {
- /* The PCI hole does not overlap the memory. */
- tolmk = tomk;
- }
-
- /* Report the memory regions. */
- idx = 10;
- ram_resource(dev, idx++, 0, 640);
- ram_resource(dev, idx++, 768, tolmk - 768);
+ u32 pci_tolm = find_pci_tolm(&dev->link[0]);
+ unsigned long tomk = 0, tolmk;
+ int idx;
+
+ outb (HIGH_RAM_ADDR, CMOS_ADDR_PORT);
+ tomk = ((unsigned long) inb(CMOS_DATA_PORT)) << 14;
+ outb (LOW_RAM_ADDR, CMOS_ADDR_PORT);
+ tomk |= ((unsigned long) inb(CMOS_DATA_PORT)) << 6;
+ tomk += 16 * 1024;
+
+ printk(BIOS_DEBUG, "Detected %lu Kbytes (%lu MiB) RAM.\n",
+ tomk, tomk / 1024);
+
+ /* Compute the top of Low memory */
+ tolmk = pci_tolm >> 10;
+ if (tolmk >= tomk) {
+ /* The PCI hole does not overlap the memory. */
+ tolmk = tomk;
+ }
+
+ /* Report the memory regions. */
+ idx = 10;
+ ram_resource(dev, idx++, 0, 640);
+ ram_resource(dev, idx++, 768, tolmk - 768);
#if CONFIG_WRITE_HIGH_TABLES==1
- /* Leave some space for ACPI, PIRQ and MP tables */
- high_tables_base = (tomk - HIGH_TABLES_SIZE) * 1024;
- high_tables_size = HIGH_TABLES_SIZE * 1024;
+ /* Leave some space for ACPI, PIRQ and MP tables */
+ high_tables_base = (tomk - HIGH_TABLES_SIZE) * 1024;
+ high_tables_size = HIGH_TABLES_SIZE * 1024;
#endif
- }
+
assign_resources(&dev->link[0]);
}