[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 8/8] seabios: pciinit: initialize pci bridge filteri
From: |
Isaku Yamahata |
Subject: |
[Qemu-devel] [PATCH 8/8] seabios: pciinit: initialize pci bridge filtering registers. |
Date: |
Thu, 17 Jun 2010 20:03:16 +0900 |
initialize pci bridge filtering registers.
Signed-off-by: Isaku Yamahata <address@hidden>
---
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 */);
}
--
1.6.6.1
- [Qemu-devel] [PATCH 0/8] seabios: pci: multi pci bus support, Isaku Yamahata, 2010/06/17
- [Qemu-devel] [PATCH 7/8] seabios: pciinit: pci bridge bus initialization., Isaku Yamahata, 2010/06/17
- [Qemu-devel] [PATCH 2/8] seabios: pciinit: factor out pci bar region allocation logic., Isaku Yamahata, 2010/06/17
- [Qemu-devel] [PATCH 4/8] seabios: pciinit: make pci bar assigner preferchable memory aware., Isaku Yamahata, 2010/06/17
- [Qemu-devel] [PATCH 1/8] seabios: pci: introduce foreachpci_in_bus() helper macro., Isaku Yamahata, 2010/06/17
- [Qemu-devel] [PATCH 5/8] seabios: pciinit: factor out bar offset calculation., Isaku Yamahata, 2010/06/17
- [Qemu-devel] [PATCH 8/8] seabios: pciinit: initialize pci bridge filtering registers.,
Isaku Yamahata <=
- [Qemu-devel] [PATCH 6/8] seabios: pciinit: make bar offset calculation pci bridge aware., Isaku Yamahata, 2010/06/17
- [Qemu-devel] [PATCH 3/8] seabios: pciinit: make pci memory space assignment 64bit aware., Isaku Yamahata, 2010/06/17
- [Qemu-devel] Re: [PATCH 0/8] seabios: pci: multi pci bus support, Michael S. Tsirkin, 2010/06/17