Unify Local APIC address definitions
[coreboot.git] / src / mainboard / emulation / qemu-x86 / northbridge.c
index 4184d14a179efffa7e81167ececaa81a3af64dd1..b961e8b60c78630e7798836afbd83828ce08cda6 100644 (file)
@@ -1,5 +1,7 @@
 #include <console/console.h>
+#include <cpu/x86/lapic_def.h>
 #include <arch/io.h>
+#include <arch/ioapic.h>
 #include <stdint.h>
 #include <device/device.h>
 #include <device/pci.h>
 #include <bitops.h>
 #include "chip.h"
 #include <delay.h>
+#include <smbios.h>
 
-static void ram_resource(device_t dev, unsigned long index,
-       unsigned long basek, unsigned long sizek)
-{
-       struct resource *resource;
+#if CONFIG_WRITE_HIGH_TABLES==1
+#include <cbmem.h>
+#endif
 
-       if (!sizek) {
-               return;
-       }
-       resource = new_resource(dev, index);
-       resource->base  = ((resource_t)basek) << 10;
-       resource->size  = ((resource_t)sizek) << 10;
-       resource->flags =  IORESOURCE_MEM | IORESOURCE_CACHEABLE | \
-               IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED;
-}
+#define CMOS_ADDR_PORT 0x70
+#define CMOS_DATA_PORT 0x71
+#define HIGH_RAM_ADDR 0x35
+#define LOW_RAM_ADDR 0x34
 
-static void tolm_test(void *gp, struct device *dev, struct resource *new)
+static unsigned long qemu_get_memory_size(void)
 {
-       struct resource **best_p = gp;
-       struct resource *best;
-       best = *best_p;
-       if (!best || (best->base > new->base)) {
-               best = new;
-       }
-       *best_p = best;
+       unsigned long tomk;
+       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;
+       return tomk;
 }
 
-static uint32_t find_pci_tolm(struct bus *bus)
+static void cpu_pci_domain_set_resources(device_t dev)
 {
-       struct resource *min;
-       uint32_t tolm;
-       min = 0;
-       search_bus_resources(bus, IORESOURCE_MEM, IORESOURCE_MEM, tolm_test, &min);
-       tolm = 0xffffffffUL;
-       if (min && tolm > min->base) {
-               tolm = min->base;
+       u32 pci_tolm = find_pci_tolm(dev->link_list);
+       unsigned long tomk = 0, tolmk;
+       int idx;
+
+       tomk = qemu_get_memory_size();
+       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;
        }
-       return tolm;
-}
-
-#if CONFIG_WRITE_HIGH_TABLES==1
-#define HIGH_TABLES_SIZE 64    // maximum size of high tables in KB
-extern uint64_t high_tables_base, high_tables_size;
-#endif
 
-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);
+       /* 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 * 1024) - HIGH_MEMORY_SIZE;
+       high_tables_size = HIGH_MEMORY_SIZE;
 #endif
-       }
-       assign_resources(&dev->link[0]);
+
+       assign_resources(dev->link_list);
 }
 
 static void cpu_pci_domain_read_resources(struct device *dev)
@@ -119,7 +72,7 @@ static void cpu_pci_domain_read_resources(struct device *dev)
        /* Reserve space for the IOAPIC.  This should be in the Southbridge,
         * but I couldn't tell which device to put it in. */
        res = new_resource(dev, 2);
-       res->base = 0xfec00000UL;
+       res->base = IO_APIC_ADDR;
        res->size = 0x100000UL;
        res->limit = 0xffffffffUL;
        res->flags = IORESOURCE_MEM | IORESOURCE_FIXED | IORESOURCE_STORED |
@@ -128,19 +81,74 @@ static void cpu_pci_domain_read_resources(struct device *dev)
        /* Reserve space for the LAPIC.  There's one in every processor, but
         * the space only needs to be reserved once, so we do it here. */
        res = new_resource(dev, 3);
-       res->base = 0xfee00000UL;
+       res->base = LOCAL_APIC_ADDR;
        res->size = 0x10000UL;
        res->limit = 0xffffffffUL;
        res->flags = IORESOURCE_MEM | IORESOURCE_FIXED | IORESOURCE_STORED |
                     IORESOURCE_ASSIGNED;
 }
 
+#if CONFIG_GENERATE_SMBIOS_TABLES
+static int qemu_get_smbios_data16(int handle, unsigned long *current)
+{
+       struct smbios_type16 *t = (struct smbios_type16 *)*current;
+       int len = sizeof(struct smbios_type16);
+
+       memset(t, 0, sizeof(struct smbios_type16));
+       t->type = SMBIOS_PHYS_MEMORY_ARRAY;
+       t->handle = handle;
+       t->length = len - 2;
+       t->location = 3; /* Location: System Board */
+       t->use = 3; /* System memory */
+       t->memory_error_correction = 3; /* No error correction */
+       t->maximum_capacity = qemu_get_memory_size();
+       *current += len;
+       return len;
+}
+
+static int qemu_get_smbios_data17(int handle, int parent_handle, unsigned long *current)
+{
+       struct smbios_type17 *t = (struct smbios_type17 *)*current;
+       int len;
+
+       memset(t, 0, sizeof(struct smbios_type17));
+       t->type = SMBIOS_MEMORY_DEVICE;
+       t->handle = handle;
+       t->phys_memory_array_handle = parent_handle;
+       t->length = sizeof(struct smbios_type17) - 2;
+       t->size = qemu_get_memory_size() / 1024;
+       t->data_width = 64;
+       t->total_width = 64;
+       t->form_factor = 9; /* DIMM */
+       t->device_locator = smbios_add_string(t->eos, "Virtual");
+       t->memory_type = 0x12; /* DDR */
+       t->type_detail = 0x80; /* Synchronous */
+       t->speed = 200;
+       t->clock_speed = 200;
+       t->manufacturer = smbios_add_string(t->eos, CONFIG_MAINBOARD_VENDOR);
+       len = t->length + smbios_string_table_len(t->eos);
+       *current += len;
+       return len;
+}
+
+static int qemu_get_smbios_data(device_t dev, int *handle, unsigned long *current)
+{
+       int len;
+       len = qemu_get_smbios_data16(*handle, current);
+       len += qemu_get_smbios_data17(*handle+1, *handle, current);
+       *handle += 2;
+       return len;
+}
+#endif
 static struct device_operations pci_domain_ops = {
        .read_resources         = cpu_pci_domain_read_resources,
        .set_resources          = cpu_pci_domain_set_resources,
-       .enable_resources       = enable_childrens_resources,
-       .init                   = 0,
+       .enable_resources       = NULL,
+       .init                   = NULL,
        .scan_bus               = pci_domain_scan_bus,
+#if CONFIG_GENERATE_SMBIOS_TABLES
+       .get_smbios_data        = qemu_get_smbios_data,
+#endif
 };
 
 static void enable_dev(struct device *dev)
@@ -152,7 +160,7 @@ static void enable_dev(struct device *dev)
        }
 }
 
-struct chip_operations cpu_emulation_qemu_x86_ops = {
+struct chip_operations mainboard_emulation_qemu_x86_ops = {
        CHIP_NAME("QEMU Northbridge")
        .enable_dev = enable_dev,
 };