aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAlexey Korolev <alexey.korolev@endace.com>2012-04-26 17:01:59 +1200
committerKevin O'Connor <kevin@koconnor.net>2012-04-26 21:52:30 -0400
commite5e5f96eb2f052e2c31a802cc3aa5329073f6c99 (patch)
tree9439fe5370a3491065ae3a092f0a29f981106c95 /src
parent37c111f253c0cad9601e1bb5beb58df50f49f24f (diff)
downloadseabios-e5e5f96eb2f052e2c31a802cc3aa5329073f6c99.tar.gz
pciinit: Migrate 64bit entries to 64bit pci regions
Migrate 64bit entries to 64bit pci regions if they do not fit in 32bit range. Signed-off-by: Alexey Korolev <alexey.korolev@endace.com>
Diffstat (limited to 'src')
-rw-r--r--src/config.h2
-rw-r--r--src/pciinit.c49
2 files changed, 47 insertions, 4 deletions
diff --git a/src/config.h b/src/config.h
index b0187a4f..bbacae71 100644
--- a/src/config.h
+++ b/src/config.h
@@ -47,6 +47,8 @@
#define BUILD_PCIMEM_START 0xe0000000
#define BUILD_PCIMEM_END 0xfec00000 /* IOAPIC is mapped at */
+#define BUILD_PCIMEM64_START 0x8000000000ULL
+#define BUILD_PCIMEM64_END 0x10000000000ULL
#define BUILD_IOAPIC_ADDR 0xfec00000
#define BUILD_HPET_ADDRESS 0xfed00000
diff --git a/src/pciinit.c b/src/pciinit.c
index 3b801c68..25b04ac7 100644
--- a/src/pciinit.c
+++ b/src/pciinit.c
@@ -386,6 +386,27 @@ static u64 pci_region_sum(struct pci_region *r)
return sum;
}
+static void pci_region_migrate_64bit_entries(struct pci_region *from,
+ struct pci_region *to)
+{
+ struct pci_region_entry **pprev = &from->list;
+ struct pci_region_entry **last = &to->list;
+ while(*pprev) {
+ if ((*pprev)->is64) {
+ struct pci_region_entry *entry;
+ entry = *pprev;
+ /* Delete the entry and move next */
+ *pprev = (*pprev)->next;
+ /* Add entry at tail to keep a sorted order */
+ entry->next = NULL;
+ *last = entry;
+ last = &entry->next;
+ }
+ else
+ pprev = &(*pprev)->next;
+ }
+}
+
static struct pci_region_entry *
pci_region_create_entry(struct pci_bus *bus, struct pci_device *dev,
int bar, u64 size, u64 align, int type, int is64)
@@ -479,7 +500,7 @@ static int pci_bios_check_devices(struct pci_bus *busses)
}
// Setup region bases (given the regions' size and alignment)
-static void pci_bios_init_root_regions(struct pci_bus *bus)
+static int pci_bios_init_root_regions(struct pci_bus *bus)
{
bus->r[PCI_REGION_TYPE_IO].base = 0xc000;
@@ -501,7 +522,8 @@ static void pci_bios_init_root_regions(struct pci_bus *bus)
if ((r_start->base < BUILD_PCIMEM_START) ||
(r_start->base > BUILD_PCIMEM_END))
// Memory range requested is larger than available.
- panic("PCI: out of address space\n");
+ return -1;
+ return 0;
}
@@ -564,6 +586,27 @@ static void pci_region_map_entries(struct pci_bus *busses, struct pci_region *r)
static void pci_bios_map_devices(struct pci_bus *busses)
{
+ if (pci_bios_init_root_regions(busses)) {
+ struct pci_region r64_mem, r64_pref;
+ r64_mem.list = NULL;
+ r64_pref.list = NULL;
+ pci_region_migrate_64bit_entries(&busses[0].r[PCI_REGION_TYPE_MEM],
+ &r64_mem);
+ pci_region_migrate_64bit_entries(&busses[0].r[PCI_REGION_TYPE_PREFMEM],
+ &r64_pref);
+
+ if (pci_bios_init_root_regions(busses))
+ panic("PCI: out of 32bit address space\n");
+
+ r64_mem.base = BUILD_PCIMEM64_START;
+ u64 sum = pci_region_sum(&r64_mem);
+ u64 align = pci_region_align(&r64_pref);
+ r64_pref.base = ALIGN(r64_mem.base + sum, align);
+ if (r64_pref.base + pci_region_sum(&r64_pref) > BUILD_PCIMEM64_END)
+ panic("PCI: out of 64bit address space\n");
+ pci_region_map_entries(busses, &r64_mem);
+ pci_region_map_entries(busses, &r64_pref);
+ }
// Map regions on each device.
int bus;
for (bus = 0; bus<=MaxPCIBus; bus++) {
@@ -608,8 +651,6 @@ pci_setup(void)
if (pci_bios_check_devices(busses))
return;
- pci_bios_init_root_regions(&busses[0]);
-
dprintf(1, "=== PCI new allocation pass #2 ===\n");
pci_bios_map_devices(busses);