>From 99ff4d141d5a460eaf20fe2d4d13117c888eae15 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 25 May 2011 13:56:52 +0200 Subject: [PATCH] init boot devices only on address space shortage --- src/pci.c | 3 ++ src/pciinit.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++------ src/util.h | 1 + 3 files changed, 74 insertions(+), 9 deletions(-) diff --git a/src/pci.c b/src/pci.c index 944a393..26c34bc 100644 --- a/src/pci.c +++ b/src/pci.c @@ -221,6 +221,9 @@ int pci_init_device(const struct pci_device_id *ids, u16 bdf, void *arg) u16 device_id = pci_config_readw(bdf, PCI_DEVICE_ID); u16 class = pci_config_readw(bdf, PCI_CLASS_DEVICE); + if (!pci_enable_device(bdf)) + return -1; + while (ids->vendid || ids->class_mask) { if ((ids->vendid == PCI_ANY_ID || ids->vendid == vendor_id) && (ids->devid == PCI_ANY_ID || ids->devid == device_id) && diff --git a/src/pciinit.c b/src/pciinit.c index 2e97b31..4aebd52 100644 --- a/src/pciinit.c +++ b/src/pciinit.c @@ -44,6 +44,7 @@ static struct pci_bus { u32 io_base, mem_base, prefmem_base; } *busses; static int busses_count; +static int boot_devices_only = 0; static void pci_bios_init_device_in_bus(int bus); static void pci_bios_check_device_in_bus(int bus); @@ -144,6 +145,50 @@ static const struct pci_device_id pci_isa_bridge_tbl[] = { #define PCI_PREF_MEMORY_ALIGN (1UL << 20) #define PCI_PREF_MEMORY_SHIFT 16 +static int is_boot_device(u16 bdf) +{ + u32 ofs, old, val; + u16 class; + + class = pci_config_readw(bdf, PCI_CLASS_DEVICE); + + /* check base class */ + switch (class >> 8) { + case PCI_BASE_CLASS_STORAGE: + case PCI_BASE_CLASS_NETWORK: + case PCI_BASE_CLASS_BRIDGE: + case PCI_BASE_CLASS_SYSTEM: + return 1; + } + + /* check class */ + switch (class) { + case PCI_CLASS_DISPLAY_VGA: + case PCI_CLASS_SERIAL_USB: + return 1; + } + + /* check if ROM present */ + ofs = pci_bar(bdf, PCI_ROM_SLOT); + old = pci_config_readl(bdf, ofs); + pci_config_writel(bdf, ofs, PCI_ROM_ADDRESS_MASK); + val = pci_config_readl(bdf, ofs); + pci_config_writel(bdf, ofs, old); + if (val != 0) { + return 1; + } + + return 0; +} + +int pci_enable_device(u16 bdf) +{ + if (boot_devices_only) { + return is_boot_device(bdf); + } + return 1; +} + static void storage_ide_init(u16 bdf, void *arg) { /* IDE: we map it as in ISA mode */ @@ -387,6 +432,9 @@ static void pci_bios_check_device(struct pci_bus *bus, u16 bdf) u16 class; int i; + if (!pci_enable_device(bdf)) + return; + class = pci_config_readw(bdf, PCI_CLASS_DEVICE); if (class == PCI_CLASS_BRIDGE_PCI) { u8 secbus = pci_config_readb(bdf, PCI_SECONDARY_BUS); @@ -437,6 +485,9 @@ static void pci_bios_map_device(struct pci_bus *bus, u16 bdf) u16 class; int i; + if (!pci_enable_device(bdf)) + return; + class = pci_config_readw(bdf, PCI_CLASS_DEVICE); if (class == PCI_CLASS_BRIDGE_PCI) { u8 secbus = pci_config_readb(bdf, PCI_SECONDARY_BUS); @@ -499,10 +550,12 @@ static void pci_bios_map_device(struct pci_bus *bus, u16 bdf) static void pci_bios_check_device_in_bus(int bus) { - int bdf, max; + int bdf, max, boot; dprintf(1, "PCI: check devices bus %d\n", bus); foreachpci_in_bus(bdf, max, bus) { + boot = is_boot_device(bdf); + dprintf(1, "PCI: check device bus %d, bfd 0x%x, boot %d\n", bus, bdf, boot); pci_bios_check_device(&busses[bus], bdf); } } @@ -568,7 +621,7 @@ static void pci_bios_init_bus_bases(struct pci_bus *bus) } } -static void pci_bios_init_root_regions(void) +static int pci_bios_init_root_regions(void) { struct pci_bus *bus = &busses[0]; u32 reserved = 0xffffffff - 0xfec00000 + 1; @@ -595,14 +648,12 @@ static void pci_bios_init_root_regions(void) bus->io_base = 0xc000; /* simple sanity check */ - /* TODO: check e820 table */ - if (bus->mem_base < RamSize) { + if (reserved > 0x10000000) { dprintf(1, "PCI: out of space for memory bars\n"); - /* Hmm, what to do now? */ + return -1; + } else { + return 0; } - - dprintf(1, "PCI: init bases bus 0 (primary)\n"); - pci_bios_init_bus_bases(bus); } void @@ -619,6 +670,15 @@ pci_setup(void) dprintf(1, "=== PCI new allocation pass #1 ===\n"); pci_bios_check_device_in_bus(0 /* host bus */); + if (pci_bios_init_root_regions() != 0) { + dprintf(1, "=== PCI new allocation pass #1a (boot only) ===\n"); + boot_devices_only = 1; + memset(busses, 0, busses_count * sizeof(struct pci_bus)); + pci_bios_check_device_in_bus(0 /* host bus */); + if (pci_bios_init_root_regions() != 0) { + /* Hmm, we are in serious trouble now */ + } + } pci_region_init(&pci_bios_io_region, 0xc000, 64 * 1024 - 1); struct pci_mem_addr addr = { @@ -628,7 +688,8 @@ pci_setup(void) pci_find_init_device(pci_mem_addr_tbl, &addr); dprintf(1, "=== PCI new allocation pass #2 ===\n"); - pci_bios_init_root_regions(); + dprintf(1, "PCI: init bases bus 0 (primary)\n"); + pci_bios_init_bus_bases(&busses[0]); pci_bios_map_device_in_bus(0 /* host bus */); pci_bios_init_device_in_bus(0 /* host bus */); diff --git a/src/util.h b/src/util.h index 2160b37..ff61031 100644 --- a/src/util.h +++ b/src/util.h @@ -381,6 +381,7 @@ u32 pci_region_size(const struct pci_region *r); // pciinit.c extern const u8 pci_irqs[4]; +int pci_enable_device(u16 bdf); void pci_bios_allocate_regions(u16 bdf, void *arg); void pci_setup(void); -- 1.7.1