This patch set allows seabios to initialize multi pci bus and 64bit BAR.
Currently seabios is able to initialize only pci root bus. However multi pci bus support is wanted because - more pci bus is wanted in qemu for many slots - pci express support is commin in qemu which requires multi pci bus. those patches on Qemu part are under way, though.
Isaku Yamahata (8): seabios: pci: introduce foreachpci_in_bus() helper macro. seabios: pciinit: factor out pci bar region allocation logic. seabios: pciinit: make pci memory space assignment 64bit aware. seabios: pciinit: make pci bar assigner preferchable memory aware. seabios: pciinit: factor out bar offset calculation. seabios: pciinit: make bar offset calculation pci bridge aware. seabios: pciinit: pci bridge bus initialization. seabios: pciinit: initialize pci bridge filtering registers.
src/pci.c | 30 ++++++ src/pci.h | 11 ++ src/pciinit.c | 310 ++++++++++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 306 insertions(+), 45 deletions(-)
This patch introduces foreachpci_in_bus() helper macro for depth first recursion. foreachpci() is for width first recursion. The macro will be used later to initialize pci bridge that requires depth first recursion.
Signed-off-by: Isaku Yamahata yamahata@valinux.co.jp --- src/pci.c | 30 ++++++++++++++++++++++++++++++ src/pci.h | 11 +++++++++++ 2 files changed, 41 insertions(+), 0 deletions(-)
diff --git a/src/pci.c b/src/pci.c index 1ab3c2c..d418b4b 100644 --- a/src/pci.c +++ b/src/pci.c @@ -157,6 +157,36 @@ pci_find_vga(void) } }
+// Helper function for foreachpci_in_bus() macro - return next devfn +int +pci_next_in_bus(int bus, int devfn) +{ + int bdf = pci_bus_devfn_to_bdf(bus, devfn); + if (pci_bdf_to_fn(bdf) == 1 + && (pci_config_readb(bdf-1, PCI_HEADER_TYPE) & 0x80) == 0) + // Last found device wasn't a multi-function device - skip to + // the next device. + devfn += 7; + + for (;;) { + if (devfn >= 0x100) + return -1; + + bdf = pci_bus_devfn_to_bdf(bus, devfn); + u16 v = pci_config_readw(bdf, PCI_VENDOR_ID); + if (v != 0x0000 && v != 0xffff) + // Device is present. + break; + + if (pci_bdf_to_fn(bdf) == 0) + devfn += 8; + else + devfn += 1; + } + + return devfn; +} + // Search for a device with the specified vendor and device ids. int pci_find_device(u16 vendid, u16 devid) diff --git a/src/pci.h b/src/pci.h index 8a21c06..26bfd40 100644 --- a/src/pci.h +++ b/src/pci.h @@ -21,6 +21,9 @@ static inline u8 pci_bdf_to_fn(u16 bdf) { static inline u16 pci_to_bdf(int bus, int dev, int fn) { return (bus<<8) | (dev<<3) | fn; } +static inline u16 pci_bus_devfn_to_bdf(int bus, u16 devfn) { + return (bus << 8) | devfn; +}
static inline u32 pci_vd(u16 vendor, u16 device) { return (device << 16) | vendor; @@ -50,6 +53,14 @@ int pci_next(int bdf, int *pmax); ; BDF >= 0 \ ; BDF=pci_next(BDF+1, &MAX))
+int pci_next_in_bus(int bus, int devfn); +#define foreachpci_in_bus(BUS, DEVFN, BDF) \ + for (DEVFN = pci_next_in_bus(BUS, 0), \ + BDF = pci_bus_devfn_to_bdf(BUS, DEVFN) \ + ; DEVFN >= 0 \ + ; DEVFN = pci_next_in_bus(BUS, DEVFN + 1), \ + BDF = pci_bus_devfn_to_bdf(BUS, DEVFN)) + // pirtable.c void create_pirtable(void);
factor out pci bar region allocation logic.
Signed-off-by: Isaku Yamahata yamahata@valinux.co.jp --- src/pciinit.c | 84 ++++++++++++++++++++++++++++++++------------------------- 1 files changed, 47 insertions(+), 37 deletions(-)
diff --git a/src/pciinit.c b/src/pciinit.c index 0556ee2..488c77b 100644 --- a/src/pciinit.c +++ b/src/pciinit.c @@ -37,6 +37,50 @@ static void pci_set_io_region_addr(u16 bdf, int region_num, u32 addr) dprintf(1, "region %d: 0x%08x\n", region_num, addr); }
+static void pci_bios_allocate_region(u16 bdf, int region_num) +{ + u32 *paddr; + int ofs; + if (region_num == PCI_ROM_SLOT) + ofs = PCI_ROM_ADDRESS; + else + ofs = PCI_BASE_ADDRESS_0 + region_num * 4; + + u32 old = pci_config_readl(bdf, ofs); + u32 mask; + if (region_num == PCI_ROM_SLOT) { + mask = PCI_ROM_ADDRESS_MASK; + pci_config_writel(bdf, ofs, mask); + } else { + if (old & PCI_BASE_ADDRESS_SPACE_IO) + mask = PCI_BASE_ADDRESS_IO_MASK; + else + mask = PCI_BASE_ADDRESS_MEM_MASK; + pci_config_writel(bdf, ofs, ~0); + } + u32 val = pci_config_readl(bdf, ofs); + pci_config_writel(bdf, ofs, old); + + if (val != 0) { + u32 size = (~(val & mask)) + 1; + if (val & PCI_BASE_ADDRESS_SPACE_IO) + paddr = &pci_bios_io_addr; + else + paddr = &pci_bios_mem_addr; + *paddr = ALIGN(*paddr, size); + pci_set_io_region_addr(bdf, region_num, *paddr); + *paddr += size; + } +} + +static void pci_bios_allocate_regions(u16 bdf) +{ + int i; + for (i = 0; i < PCI_NUM_REGIONS; i++) { + pci_bios_allocate_region(bdf, i); + } +} + /* return the global irq number corresponding to a given device irq pin. We could also use the bus number to have a more precise mapping. */ @@ -78,8 +122,7 @@ static void pci_bios_init_bridges(u16 bdf) static void pci_bios_init_device(u16 bdf) { int class; - u32 *paddr; - int i, pin, pic_irq, vendor_id, device_id; + int pin, pic_irq, vendor_id, device_id;
class = pci_config_readw(bdf, PCI_CLASS_DEVICE); vendor_id = pci_config_readw(bdf, PCI_VENDOR_ID); @@ -94,7 +137,7 @@ static void pci_bios_init_device(u16 bdf) /* PIIX3/PIIX4 IDE */ pci_config_writew(bdf, 0x40, 0x8000); // enable IDE0 pci_config_writew(bdf, 0x42, 0x8000); // enable IDE1 - goto default_map; + pci_bios_allocate_regions(bdf); } else { /* IDE: we map it as in ISA mode */ pci_set_io_region_addr(bdf, 0, PORT_ATA1_CMD_BASE); @@ -121,41 +164,8 @@ static void pci_bios_init_device(u16 bdf) } break; default: - default_map: /* default memory mappings */ - for (i = 0; i < PCI_NUM_REGIONS; i++) { - int ofs; - if (i == PCI_ROM_SLOT) - ofs = PCI_ROM_ADDRESS; - else - ofs = PCI_BASE_ADDRESS_0 + i * 4; - - u32 old = pci_config_readl(bdf, ofs); - u32 mask; - if (i == PCI_ROM_SLOT) { - mask = PCI_ROM_ADDRESS_MASK; - pci_config_writel(bdf, ofs, mask); - } else { - if (old & PCI_BASE_ADDRESS_SPACE_IO) - mask = PCI_BASE_ADDRESS_IO_MASK; - else - mask = PCI_BASE_ADDRESS_MEM_MASK; - pci_config_writel(bdf, ofs, ~0); - } - u32 val = pci_config_readl(bdf, ofs); - pci_config_writel(bdf, ofs, old); - - if (val != 0) { - u32 size = (~(val & mask)) + 1; - if (val & PCI_BASE_ADDRESS_SPACE_IO) - paddr = &pci_bios_io_addr; - else - paddr = &pci_bios_mem_addr; - *paddr = ALIGN(*paddr, size); - pci_set_io_region_addr(bdf, i, *paddr); - *paddr += size; - } - } + pci_bios_allocate_regions(bdf); break; }
make pci memory space assignment 64bit aware. If 64bit memory space is found while assigning pci memory space, clear higher bit and skip to next bar.
This patch is preparation for q35 chipset initialization which has 64bit bar.
Signed-off-by: Isaku Yamahata yamahata@valinux.co.jp --- src/pciinit.c | 19 +++++++++++++++++-- 1 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/pciinit.c b/src/pciinit.c index 488c77b..b635e44 100644 --- a/src/pciinit.c +++ b/src/pciinit.c @@ -37,7 +37,12 @@ static void pci_set_io_region_addr(u16 bdf, int region_num, u32 addr) dprintf(1, "region %d: 0x%08x\n", region_num, addr); }
-static void pci_bios_allocate_region(u16 bdf, int region_num) +/* + * return value + * 0: 32bit BAR + * non 0: 64bit BAR + */ +static int pci_bios_allocate_region(u16 bdf, int region_num) { u32 *paddr; int ofs; @@ -71,13 +76,23 @@ static void pci_bios_allocate_region(u16 bdf, int region_num) pci_set_io_region_addr(bdf, region_num, *paddr); *paddr += size; } + + int is_64bit = !(val & PCI_BASE_ADDRESS_SPACE_IO) && + (val & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64; + if (is_64bit) { + pci_config_writel(bdf, ofs + 4, 0); + } + return is_64bit; }
static void pci_bios_allocate_regions(u16 bdf) { int i; for (i = 0; i < PCI_NUM_REGIONS; i++) { - pci_bios_allocate_region(bdf, i); + int is_64bit = pci_bios_allocate_region(bdf, i); + if (is_64bit){ + i++; + } } }
Make pci bar assigner preferchable memory aware. This is needed for PCI bridge support because memory space and prefetchable memory space is filtered independently based on memory base/limit and prefetchable memory base/limit of pci bridge. On bus 0, such a distinction isn't necessary so keep existing behavior by checking bus=0.
Signed-off-by: Isaku Yamahata yamahata@valinux.co.jp --- src/pciinit.c | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/src/pciinit.c b/src/pciinit.c index b635e44..b6ab157 100644 --- a/src/pciinit.c +++ b/src/pciinit.c @@ -16,6 +16,7 @@
static u32 pci_bios_io_addr; static u32 pci_bios_mem_addr; +static u32 pci_bios_prefmem_addr; /* host irqs corresponding to PCI irqs A-D */ static u8 pci_irqs[4] = { 10, 10, 11, 11 @@ -70,6 +71,12 @@ static int pci_bios_allocate_region(u16 bdf, int region_num) u32 size = (~(val & mask)) + 1; if (val & PCI_BASE_ADDRESS_SPACE_IO) paddr = &pci_bios_io_addr; + else if ((val & PCI_BASE_ADDRESS_MEM_PREFETCH) && + /* keep behaviour on bus = 0 */ + pci_bdf_to_bus(bdf) != 0 && + /* If pci_bios_prefmem_addr == 0, keep old behaviour */ + pci_bios_prefmem_addr != 0) + paddr = &pci_bios_prefmem_addr; else paddr = &pci_bios_mem_addr; *paddr = ALIGN(*paddr, size); @@ -221,6 +228,9 @@ pci_setup(void) pci_bios_io_addr = 0xc000; pci_bios_mem_addr = BUILD_PCIMEM_START;
+ /* pci_bios_mem_addr + <some value> */ + pci_bios_prefmem_addr = pci_bios_mem_addr + 0x08000000; + int bdf, max; foreachpci(bdf, max) { pci_bios_init_bridges(bdf);
This patch factors out bar offset calculation. Later the calculation logic will be enhanced.
Signed-off-by: Isaku Yamahata yamahata@valinux.co.jp --- src/pciinit.c | 20 ++++++++++---------- 1 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/src/pciinit.c b/src/pciinit.c index b6ab157..6ba51f2 100644 --- a/src/pciinit.c +++ b/src/pciinit.c @@ -22,15 +22,19 @@ static u8 pci_irqs[4] = { 10, 10, 11, 11 };
+static u32 pci_bar(u16 bdf, int region_num) +{ + if (region_num != PCI_ROM_SLOT) { + return PCI_BASE_ADDRESS_0 + region_num * 4; + } + return PCI_ROM_ADDRESS; +} + static void pci_set_io_region_addr(u16 bdf, int region_num, u32 addr) { u32 ofs, old_addr;
- if (region_num == PCI_ROM_SLOT) { - ofs = PCI_ROM_ADDRESS; - } else { - ofs = PCI_BASE_ADDRESS_0 + region_num * 4; - } + ofs = pci_bar(bdf, region_num);
old_addr = pci_config_readl(bdf, ofs);
@@ -46,11 +50,7 @@ static void pci_set_io_region_addr(u16 bdf, int region_num, u32 addr) static int pci_bios_allocate_region(u16 bdf, int region_num) { u32 *paddr; - int ofs; - if (region_num == PCI_ROM_SLOT) - ofs = PCI_ROM_ADDRESS; - else - ofs = PCI_BASE_ADDRESS_0 + region_num * 4; + u32 ofs = pci_bar(bdf, region_num);
u32 old = pci_config_readl(bdf, ofs); u32 mask;
This patch makes pci bar offset calculation pci bridge aware. The offset of pci bridge rom is different from normal device.
Signed-off-by: Isaku Yamahata yamahata@valinux.co.jp --- src/pciinit.c | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-)
diff --git a/src/pciinit.c b/src/pciinit.c index 6ba51f2..1c2c8c6 100644 --- a/src/pciinit.c +++ b/src/pciinit.c @@ -27,7 +27,11 @@ static u32 pci_bar(u16 bdf, int region_num) if (region_num != PCI_ROM_SLOT) { return PCI_BASE_ADDRESS_0 + region_num * 4; } - return PCI_ROM_ADDRESS; + +#define PCI_HEADER_TYPE_MULTI_FUNCTION 0x80 + u8 type = pci_config_readb(bdf, PCI_HEADER_TYPE); + type &= ~PCI_HEADER_TYPE_MULTI_FUNCTION; + return type == PCI_HEADER_TYPE_BRIDGE ? PCI_ROM_ADDRESS1 : PCI_ROM_ADDRESS; }
static void pci_set_io_region_addr(u16 bdf, int region_num, u32 addr)
pci bridge bus initialization.
Signed-off-by: Isaku Yamahata yamahata@valinux.co.jp --- src/pciinit.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 70 insertions(+), 0 deletions(-)
diff --git a/src/pciinit.c b/src/pciinit.c index 1c2c8c6..fe6848a 100644 --- a/src/pciinit.c +++ b/src/pciinit.c @@ -220,6 +220,74 @@ static void pci_bios_init_device(u16 bdf) } }
+static void +pci_bios_init_bus_rec(int bus, u8 *pci_bus) +{ + int devfn, bdf; + u16 class; + + dprintf(1, "PCI: %s bus = 0x%x\n", __func__, bus); + + /* prevent accidental access to unintended devices */ + foreachpci_in_bus(bus, devfn, bdf) { + class = pci_config_readw(bdf, PCI_CLASS_DEVICE); + if (class == PCI_CLASS_BRIDGE_PCI) { + pci_config_writeb(bdf, PCI_SECONDARY_BUS, 255); + pci_config_writeb(bdf, PCI_SUBORDINATE_BUS, 0); + } + } + + foreachpci_in_bus(bus, devfn, bdf) { + class = pci_config_readw(bdf, PCI_CLASS_DEVICE); + if (class != PCI_CLASS_BRIDGE_PCI) { + continue; + } + dprintf(1, "PCI: %s bdf = 0x%x\n", __func__, bdf); + + u8 pribus = pci_config_readb(bdf, PCI_PRIMARY_BUS); + if (pribus != bus) { + dprintf(1, "PCI: primary bus = 0x%x -> 0x%x\n", pribus, bus); + pci_config_writeb(bdf, PCI_PRIMARY_BUS, bus); + } else { + dprintf(1, "PCI: primary bus = 0x%x\n", pribus); + } + + u8 secbus = pci_config_readb(bdf, PCI_SECONDARY_BUS); + (*pci_bus)++; + if (*pci_bus != secbus) { + dprintf(1, "PCI: secondary bus = 0x%x -> 0x%x\n", + secbus, *pci_bus); + secbus = *pci_bus; + pci_config_writeb(bdf, PCI_SECONDARY_BUS, secbus); + } else { + dprintf(1, "PCI: secondary bus = 0x%x\n", secbus); + } + + /* set to max for access to all subordinate buses. + later set it to accurate value */ + u8 subbus = pci_config_readb(bdf, PCI_SUBORDINATE_BUS); + pci_config_writeb(bdf, PCI_SUBORDINATE_BUS, 255); + + pci_bios_init_bus_rec(secbus, pci_bus); + + if (subbus != *pci_bus) { + dprintf(1, "PCI: subordinate bus = 0x%x -> 0x%x\n", + subbus, *pci_bus); + subbus = *pci_bus; + } else { + dprintf(1, "PCI: subordinate bus = 0x%x\n", subbus); + } + pci_config_writeb(bdf, PCI_SUBORDINATE_BUS, subbus); + } +} + +static void +pci_bios_init_bus(void) +{ + u8 pci_bus = 0; + pci_bios_init_bus_rec(0 /* host bus */, &pci_bus); +} + void pci_setup(void) { @@ -235,6 +303,8 @@ pci_setup(void) /* pci_bios_mem_addr + <some value> */ pci_bios_prefmem_addr = pci_bios_mem_addr + 0x08000000;
+ pci_bios_init_bus(); + int bdf, max; foreachpci(bdf, max) { pci_bios_init_bridges(bdf);
initialize pci bridge filtering registers.
Signed-off-by: Isaku Yamahata yamahata@valinux.co.jp --- src/pciinit.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 114 insertions(+), 3 deletions(-)
diff --git a/src/pciinit.c b/src/pciinit.c index fe6848a..f68a690 100644 --- a/src/pciinit.c +++ b/src/pciinit.c @@ -14,6 +14,8 @@ #define PCI_ROM_SLOT 6 #define PCI_NUM_REGIONS 7
+static void pci_bios_init_device_in_bus(int bus); + static u32 pci_bios_io_addr; static u32 pci_bios_mem_addr; static u32 pci_bios_prefmem_addr; @@ -145,6 +147,106 @@ static void pci_bios_init_bridges(u16 bdf) } }
+#define PCI_IO_ALIGN 4096 +#define PCI_IO_SHIFT 8 +#define PCI_MEMORY_ALIGN (1UL << 20) +#define PCI_MEMORY_SHIFT 16 +#define PCI_PREF_MEMORY_ALIGN (1UL << 20) +#define PCI_PREF_MEMORY_SHIFT 16 + +static void pci_bios_init_device_bridge(u16 bdf) +{ + u32 io_old; + u32 mem_old; + u32 prefmem_old; + + u32 io_base; + u32 io_end; + u32 mem_base; + u32 mem_end; + u32 prefmem_base; + u32 prefmem_end; + + pci_bios_allocate_region(bdf, 0); + pci_bios_allocate_region(bdf, 1); + pci_bios_allocate_region(bdf, PCI_ROM_SLOT); + + io_old = pci_bios_io_addr; + mem_old = pci_bios_mem_addr; + prefmem_old = pci_bios_prefmem_addr; + + /* IO BASE is assumed to be 16 bit */ + pci_bios_io_addr = ALIGN(pci_bios_io_addr, PCI_IO_ALIGN); + pci_bios_mem_addr = ALIGN(pci_bios_mem_addr, PCI_MEMORY_ALIGN); + pci_bios_prefmem_addr = + ALIGN(pci_bios_prefmem_addr, PCI_PREF_MEMORY_ALIGN); + + io_base = pci_bios_io_addr; + mem_base = pci_bios_mem_addr; + prefmem_base = pci_bios_prefmem_addr; + + u8 secbus = pci_config_readb(bdf, PCI_SECONDARY_BUS); + if (secbus > 0) { + pci_bios_init_device_in_bus(secbus); + } + + pci_bios_io_addr = ALIGN(pci_bios_io_addr, PCI_IO_ALIGN); + pci_bios_mem_addr = ALIGN(pci_bios_mem_addr, PCI_MEMORY_ALIGN); + pci_bios_prefmem_addr = + ALIGN(pci_bios_prefmem_addr, PCI_PREF_MEMORY_ALIGN); + + io_end = pci_bios_io_addr; + if (io_end == io_base) { + pci_bios_io_addr = io_old; + io_base = 0xffff; + io_end = 1; + } + pci_config_writeb(bdf, PCI_IO_BASE, io_base >> PCI_IO_SHIFT); + pci_config_writew(bdf, PCI_IO_BASE_UPPER16, 0); + pci_config_writeb(bdf, PCI_IO_LIMIT, (io_end - 1) >> PCI_IO_SHIFT); + pci_config_writew(bdf, PCI_IO_LIMIT_UPPER16, 0); + + mem_end = pci_bios_mem_addr; + if (mem_end == mem_base) { + pci_bios_mem_addr = mem_old; + mem_base = 0xffffffff; + mem_end = 1; + } + pci_config_writew(bdf, PCI_MEMORY_BASE, mem_base >> PCI_MEMORY_SHIFT); + pci_config_writew(bdf, PCI_MEMORY_LIMIT, (mem_end -1) >> PCI_MEMORY_SHIFT); + + prefmem_end = pci_bios_prefmem_addr; + if (prefmem_end == prefmem_base) { + pci_bios_prefmem_addr = prefmem_old; + prefmem_base = 0xffffffff; + prefmem_end = 1; + } + pci_config_writew(bdf, PCI_PREF_MEMORY_BASE, + prefmem_base >> PCI_PREF_MEMORY_SHIFT); + pci_config_writew(bdf, PCI_PREF_MEMORY_LIMIT, + (prefmem_end - 1) >> PCI_PREF_MEMORY_SHIFT); + pci_config_writel(bdf, PCI_PREF_BASE_UPPER32, 0); + pci_config_writel(bdf, PCI_PREF_LIMIT_UPPER32, 0); + + dprintf(1, "PCI: br io = [0x%x, 0x%x)\n", io_base, io_end); + dprintf(1, "PCI: br mem = [0x%x, 0x%x)\n", mem_base, mem_end); + dprintf(1, "PCI: br pref = [0x%x, 0x%x)\n", prefmem_base, prefmem_end); + + u16 cmd = pci_config_readw(bdf, PCI_COMMAND); + cmd &= ~PCI_COMMAND_IO; + if (io_end > io_base) { + cmd |= PCI_COMMAND_IO; + } + cmd &= ~PCI_COMMAND_MEMORY; + if (mem_end > mem_base || prefmem_end > prefmem_base) { + cmd |= PCI_COMMAND_MEMORY; + } + cmd |= PCI_COMMAND_MASTER; + pci_config_writew(bdf, PCI_COMMAND, cmd); + + pci_config_maskw(bdf, PCI_BRIDGE_CONTROL, 0, PCI_BRIDGE_CTL_SERR); +} + static void pci_bios_init_device(u16 bdf) { int class; @@ -189,6 +291,9 @@ static void pci_bios_init_device(u16 bdf) pci_set_io_region_addr(bdf, 0, 0x80800000); } break; + case PCI_CLASS_BRIDGE_PCI: + pci_bios_init_device_bridge(bdf); + break; default: /* default memory mappings */ pci_bios_allocate_regions(bdf); @@ -220,6 +325,14 @@ static void pci_bios_init_device(u16 bdf) } }
+static void pci_bios_init_device_in_bus(int bus) +{ + int devfn, bdf; + foreachpci_in_bus(bus, devfn, bdf) { + pci_bios_init_device(bdf); + } +} + static void pci_bios_init_bus_rec(int bus, u8 *pci_bus) { @@ -309,7 +422,5 @@ pci_setup(void) foreachpci(bdf, max) { pci_bios_init_bridges(bdf); } - foreachpci(bdf, max) { - pci_bios_init_device(bdf); - } + pci_bios_init_device_in_bus(0 /* host bus */); }
Isaku Yamahata wrote:
This patch set allows seabios to initialize multi pci bus and 64bit BAR.
It seems like this is starting to replicate things that are already in coreboot. Is that an accurate observation?
//Peter
On Thu, Jun 17, 2010 at 01:15:18PM +0200, Peter Stuge wrote:
Isaku Yamahata wrote:
This patch set allows seabios to initialize multi pci bus and 64bit BAR.
It seems like this is starting to replicate things that are already in coreboot. Is that an accurate observation?
I haven't looked at coreboot. So I don't know. If so, the existing bar assignment is already replication, isn't it.
Isaku Yamahata wrote:
This patch set allows seabios to initialize multi pci bus and 64bit BAR.
It seems like this is starting to replicate things that are already in coreboot. Is that an accurate observation?
I haven't looked at coreboot. So I don't know.
It it a firmware for many PC systems. It brings up CPU, RAM and buses, including HyperTransport, PCI Express, PCI and PnP.
If so, the existing bar assignment is already replication, isn't it.
That would also be true yes, however maybe the resource allocator in SeaBIOS for qemu is so far simpler than the generic one in coreboot, so it was not a lot of duplicated code, while the PCIe seems to be a fairly big addition, of something that I think coreboot may already be able to do. It seems to me that now may be a time to consider if and how coreboot fits with qemu.
//Peter
On Fri, Jun 18, 2010 at 07:58:23AM +0200, Peter Stuge wrote:
Isaku Yamahata wrote:
This patch set allows seabios to initialize multi pci bus and 64bit BAR.
It seems like this is starting to replicate things that are already in coreboot. Is that an accurate observation?
I haven't looked at coreboot. So I don't know.
It it a firmware for many PC systems. It brings up CPU, RAM and buses, including HyperTransport, PCI Express, PCI and PnP.
If so, the existing bar assignment is already replication, isn't it.
That would also be true yes, however maybe the resource allocator in SeaBIOS for qemu is so far simpler than the generic one in coreboot, so it was not a lot of duplicated code, while the PCIe seems to be a fairly big addition, of something that I think coreboot may already be able to do. It seems to me that now may be a time to consider if and how coreboot fits with qemu.
If the consensus for coreboot is made, I'm fine with it and will follow it. I think the switch would be a much longer term issue than PCIe.
FWIW, the following is my plan for seabios. - factor out i440fx specific code and other device specific code. - add q35 chip set specific code, dsdt and mcfg - and then, make qemu give seabios hints to pci bus numbering.
On Thu, Jun 17, 2010 at 08:03:08PM +0900, Isaku Yamahata wrote:
This patch set allows seabios to initialize multi pci bus and 64bit BAR.
Currently seabios is able to initialize only pci root bus. However multi pci bus support is wanted because
- more pci bus is wanted in qemu for many slots
- pci express support is commin in qemu which requires multi pci bus.
those patches on Qemu part are under way, though.
Not that I object, but - does it really require multi bus? Why?
Isaku Yamahata (8): seabios: pci: introduce foreachpci_in_bus() helper macro. seabios: pciinit: factor out pci bar region allocation logic. seabios: pciinit: make pci memory space assignment 64bit aware. seabios: pciinit: make pci bar assigner preferchable memory aware. seabios: pciinit: factor out bar offset calculation. seabios: pciinit: make bar offset calculation pci bridge aware. seabios: pciinit: pci bridge bus initialization. seabios: pciinit: initialize pci bridge filtering registers.
src/pci.c | 30 ++++++ src/pci.h | 11 ++ src/pciinit.c | 310 ++++++++++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 306 insertions(+), 45 deletions(-)
On Thu, Jun 17, 2010 at 02:17:20PM +0300, Michael S. Tsirkin wrote:
On Thu, Jun 17, 2010 at 08:03:08PM +0900, Isaku Yamahata wrote:
This patch set allows seabios to initialize multi pci bus and 64bit BAR.
Currently seabios is able to initialize only pci root bus. However multi pci bus support is wanted because
- more pci bus is wanted in qemu for many slots
- pci express support is commin in qemu which requires multi pci bus.
those patches on Qemu part are under way, though.
Not that I object, but - does it really require multi bus? Why?
I should have explained about pci express a bit more. Express defines root/upstream/upstream port. They are shown to software as pci-to-pci bride. Express slot to which express device is inserted is under a root or downstream port. That means multi bus. Native hot plug is implemented in root or downstream port. Again that means multi bus.
I heard that some windows device driver checks pci-to-pci bridge existence. Perhaps others may know this better.