[SeaBIOS] [RFC 2/2] pci_device: Add pci domain support
Zihan Yang
whois.zihan.yang at gmail.com
Thu Aug 2 04:39:15 CEST 2018
Most part of seabios assume only PCI domain 0. This patch adds support
for multiple domain in pci devices
Signed-off-by: Zihan Yang <whois.zihan.yang at gmail.com>
---
src/fw/coreboot.c | 2 +-
src/fw/csm.c | 2 +-
src/fw/paravirt.c | 2 +-
src/fw/pciinit.c | 191 +++++++++++++++++++++++++++++++++--------------------
src/hw/pci.c | 69 ++++++++++---------
src/hw/pci.h | 42 ++++++++----
src/hw/pci_ids.h | 7 +-
src/hw/pcidevice.c | 8 ++-
src/hw/pcidevice.h | 10 ++-
9 files changed, 206 insertions(+), 127 deletions(-)
diff --git a/src/fw/coreboot.c b/src/fw/coreboot.c
index 7c0954b..c955dfd 100644
--- a/src/fw/coreboot.c
+++ b/src/fw/coreboot.c
@@ -254,7 +254,7 @@ coreboot_platform_setup(void)
{
if (!CONFIG_COREBOOT)
return;
- pci_probe_devices();
+ pci_probe_devices(0);
struct cb_memory *cbm = CBMemTable;
if (!cbm)
diff --git a/src/fw/csm.c b/src/fw/csm.c
index 03b4bb8..e94f614 100644
--- a/src/fw/csm.c
+++ b/src/fw/csm.c
@@ -63,7 +63,7 @@ static void
csm_maininit(struct bregs *regs)
{
interface_init();
- pci_probe_devices();
+ pci_probe_devices(0);
csm_compat_table.PnPInstallationCheckSegment = SEG_BIOS;
csm_compat_table.PnPInstallationCheckOffset = get_pnp_offset();
diff --git a/src/fw/paravirt.c b/src/fw/paravirt.c
index 6b14542..ef4d487 100644
--- a/src/fw/paravirt.c
+++ b/src/fw/paravirt.c
@@ -155,7 +155,7 @@ qemu_platform_setup(void)
return;
if (runningOnXen()) {
- pci_probe_devices();
+ pci_probe_devices(0);
xen_hypercall_setup();
xen_biostable_setup();
return;
diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c
index 6e6a434..71508d5 100644
--- a/src/fw/pciinit.c
+++ b/src/fw/pciinit.c
@@ -51,6 +51,7 @@ u64 pcimem_end = BUILD_PCIMEM_END;
u64 pcimem64_start = BUILD_PCIMEM64_START;
u64 pcimem64_end = BUILD_PCIMEM64_END;
u64 pci_io_low_end = 0xa000;
+u64 pxb_mcfg_size = 0;
struct pci_region_entry {
struct pci_device *dev;
@@ -405,19 +406,21 @@ static void pci_bios_init_device(struct pci_device *pci)
/* map the interrupt */
u16 bdf = pci->bdf;
- int pin = pci_config_readb(bdf, PCI_INTERRUPT_PIN);
+ int pin = pci_config_readb_dom(bdf, PCI_INTERRUPT_PIN, pci->domain_nr);
if (pin != 0)
- pci_config_writeb(bdf, PCI_INTERRUPT_LINE, pci_slot_get_irq(pci, pin));
+ pci_config_writeb_dom(bdf, PCI_INTERRUPT_LINE, pci_slot_get_irq(pci, pin),
+ pci->domain_nr);
pci_init_device(pci_device_tbl, pci, NULL);
/* enable memory mappings */
- pci_config_maskw(bdf, PCI_COMMAND, 0,
- PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_SERR);
+ pci_config_maskw_dom(bdf, PCI_COMMAND, 0,
+ PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_SERR,
+ pci->domain_nr);
/* enable SERR# for forwarding */
if (pci->header_type & PCI_HEADER_TYPE_BRIDGE)
- pci_config_maskw(bdf, PCI_BRIDGE_CONTROL, 0,
- PCI_BRIDGE_CTL_SERR);
+ pci_config_maskw_dom(bdf, PCI_BRIDGE_CONTROL, 0,
+ PCI_BRIDGE_CTL_SERR, pci->domain_nr);
}
static void pci_bios_init_devices(void)
@@ -520,6 +523,10 @@ static void pxb_mem_addr_setup(struct pci_device *dev, void *arg)
* read mcfg_base and mcfg_size from it just now. Instead, we directly add
* this item to e820 */
e820_add(mcfg_base.val, mcfg_size, E820_RESERVED);
+
+ /* Add PXBHosts so that we can can initialize them later */
+ ++PXBHosts;
+ pxb_mcfg_size += mcfg_size;
}
static const struct pci_device_id pci_platform_tbl[] = {
@@ -540,19 +547,21 @@ static void pci_bios_init_platform(void)
}
}
-static u8 pci_find_resource_reserve_capability(u16 bdf)
+static u8 pci_find_resource_reserve_capability(u16 bdf, int domain_nr)
{
- if (pci_config_readw(bdf, PCI_VENDOR_ID) == PCI_VENDOR_ID_REDHAT &&
- pci_config_readw(bdf, PCI_DEVICE_ID) ==
- PCI_DEVICE_ID_REDHAT_ROOT_PORT) {
+ if (pci_config_readw_dom(bdf, PCI_VENDOR_ID, domain_nr) == PCI_VENDOR_ID_REDHAT &&
+ (pci_config_readw_dom(bdf, PCI_DEVICE_ID, domain_nr) ==
+ PCI_DEVICE_ID_REDHAT_ROOT_PORT ||
+ pci_config_readw_dom(bdf, PCI_DEVICE_ID, domain_nr) ==
+ PCI_DEVICE_ID_REDHAT_PCIE_BRIDGE)) {
u8 cap = 0;
do {
- cap = pci_find_capability(bdf, PCI_CAP_ID_VNDR, cap);
+ cap = pci_find_capability_dom(bdf, PCI_CAP_ID_VNDR, cap, domain_nr);
} while (cap &&
- pci_config_readb(bdf, cap + PCI_CAP_REDHAT_TYPE_OFFSET) !=
+ pci_config_readb_dom(bdf, cap + PCI_CAP_REDHAT_TYPE_OFFSET, domain_nr) !=
REDHAT_CAP_RESOURCE_RESERVE);
if (cap) {
- u8 cap_len = pci_config_readb(bdf, cap + PCI_CAP_FLAGS);
+ u8 cap_len = pci_config_readb_dom(bdf, cap + PCI_CAP_FLAGS, domain_nr);
if (cap_len < RES_RESERVE_CAP_SIZE) {
dprintf(1, "PCI: QEMU resource reserve cap length %d is invalid\n",
cap_len);
@@ -570,7 +579,7 @@ static u8 pci_find_resource_reserve_capability(u16 bdf)
****************************************************************/
static void
-pci_bios_init_bus_rec(int bus, u8 *pci_bus)
+pci_bios_init_bus_rec(int bus, u8 *pci_bus, int domain_nr)
{
int bdf;
u16 class;
@@ -578,54 +587,54 @@ pci_bios_init_bus_rec(int bus, u8 *pci_bus)
dprintf(1, "PCI: %s bus = 0x%x\n", __func__, bus);
/* prevent accidental access to unintended devices */
- foreachbdf(bdf, bus) {
- class = pci_config_readw(bdf, PCI_CLASS_DEVICE);
+ foreachbdf_dom(bdf, bus, domain_nr) {
+ class = pci_config_readw_dom(bdf, PCI_CLASS_DEVICE, domain_nr);
if (class == PCI_CLASS_BRIDGE_PCI) {
- pci_config_writeb(bdf, PCI_SECONDARY_BUS, 255);
- pci_config_writeb(bdf, PCI_SUBORDINATE_BUS, 0);
+ pci_config_writeb_dom(bdf, PCI_SECONDARY_BUS, 255, domain_nr);
+ pci_config_writeb_dom(bdf, PCI_SUBORDINATE_BUS, 0, domain_nr);
}
}
- foreachbdf(bdf, bus) {
- class = pci_config_readw(bdf, PCI_CLASS_DEVICE);
+ foreachbdf_dom(bdf, bus, domain_nr) {
+ class = pci_config_readw_dom(bdf, PCI_CLASS_DEVICE, domain_nr);
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);
+ u8 pribus = pci_config_readb_dom(bdf, PCI_PRIMARY_BUS, domain_nr);
if (pribus != bus) {
dprintf(1, "PCI: primary bus = 0x%x -> 0x%x\n", pribus, bus);
- pci_config_writeb(bdf, PCI_PRIMARY_BUS, bus);
+ pci_config_writeb_dom(bdf, PCI_PRIMARY_BUS, bus, domain_nr);
} else {
dprintf(1, "PCI: primary bus = 0x%x\n", pribus);
}
- u8 secbus = pci_config_readb(bdf, PCI_SECONDARY_BUS);
+ u8 secbus = pci_config_readb_dom(bdf, PCI_SECONDARY_BUS, domain_nr);
(*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);
+ pci_config_writeb_dom(bdf, PCI_SECONDARY_BUS, secbus, domain_nr);
} 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);
+ u8 subbus = pci_config_readb_dom(bdf, PCI_SUBORDINATE_BUS, domain_nr);
+ pci_config_writeb_dom(bdf, PCI_SUBORDINATE_BUS, 255, domain_nr);
- pci_bios_init_bus_rec(secbus, pci_bus);
+ pci_bios_init_bus_rec(secbus, pci_bus, domain_nr);
if (subbus != *pci_bus) {
u8 res_bus = *pci_bus;
- u8 cap = pci_find_resource_reserve_capability(bdf);
+ u8 cap = pci_find_resource_reserve_capability(bdf, domain_nr);
if (cap) {
- u32 tmp_res_bus = pci_config_readl(bdf,
- cap + RES_RESERVE_BUS_RES);
+ u32 tmp_res_bus = pci_config_readl_dom(bdf,
+ cap + RES_RESERVE_BUS_RES, domain_nr);
if (tmp_res_bus != (u32)-1) {
res_bus = tmp_res_bus & 0xFF;
if ((u8)(res_bus + secbus) < secbus ||
@@ -648,7 +657,7 @@ pci_bios_init_bus_rec(int bus, u8 *pci_bus)
} else {
dprintf(1, "PCI: subordinate bus = 0x%x\n", subbus);
}
- pci_config_writeb(bdf, PCI_SUBORDINATE_BUS, subbus);
+ pci_config_writeb_dom(bdf, PCI_SUBORDINATE_BUS, subbus, domain_nr);
}
}
@@ -658,16 +667,29 @@ pci_bios_init_bus(void)
u8 extraroots = romfile_loadint("etc/extra-pci-roots", 0);
u8 pci_bus = 0;
- pci_bios_init_bus_rec(0 /* host bus */, &pci_bus);
+ pci_bios_init_bus_rec(0 /* host bus */, &pci_bus, 0);
if (extraroots) {
while (pci_bus < 0xff) {
pci_bus++;
- pci_bios_init_bus_rec(pci_bus, &pci_bus);
+ pci_bios_init_bus_rec(pci_bus, &pci_bus, 0);
}
}
}
+static void
+pci_bios_init_pxb_bus(int domain_nr)
+{
+ u8 pci_bus = 0;
+
+ // FIX ME! Hardcoded ports is not a good idea at all!
+ pci_bios_init_bus_rec(0, &pci_bus, domain_nr);
+
+ while (pci_bus < 0xff) {
+ pci_bus++;
+ pci_bios_init_bus_rec(pci_bus, &pci_bus, domain_nr);
+ }
+}
/****************************************************************
* Bus sizing
@@ -675,17 +697,18 @@ pci_bios_init_bus(void)
static void
pci_bios_get_bar(struct pci_device *pci, int bar,
- int *ptype, u64 *psize, int *pis64)
+ int *ptype, u64 *psize, int *pis64,
+ int domain_nr)
{
u32 ofs = pci_bar(pci, bar);
u16 bdf = pci->bdf;
- u32 old = pci_config_readl(bdf, ofs);
+ u32 old = pci_config_readl_dom(bdf, ofs, domain_nr);
int is64 = 0, type = PCI_REGION_TYPE_MEM;
u64 mask;
if (bar == PCI_ROM_SLOT) {
mask = PCI_ROM_ADDRESS_MASK;
- pci_config_writel(bdf, ofs, mask);
+ pci_config_writel_dom(bdf, ofs, mask, domain_nr);
} else {
if (old & PCI_BASE_ADDRESS_SPACE_IO) {
mask = PCI_BASE_ADDRESS_IO_MASK;
@@ -697,15 +720,15 @@ pci_bios_get_bar(struct pci_device *pci, int bar,
is64 = ((old & PCI_BASE_ADDRESS_MEM_TYPE_MASK)
== PCI_BASE_ADDRESS_MEM_TYPE_64);
}
- pci_config_writel(bdf, ofs, ~0);
+ pci_config_writel_dom(bdf, ofs, ~0, domain_nr);
}
- u64 val = pci_config_readl(bdf, ofs);
- pci_config_writel(bdf, ofs, old);
+ u64 val = pci_config_readl_dom(bdf, ofs, domain_nr);
+ pci_config_writel_dom(bdf, ofs, old, domain_nr);
if (is64) {
- u32 hold = pci_config_readl(bdf, ofs + 4);
- pci_config_writel(bdf, ofs + 4, ~0);
- u32 high = pci_config_readl(bdf, ofs + 4);
- pci_config_writel(bdf, ofs + 4, hold);
+ u32 hold = pci_config_readl_dom(bdf, ofs + 4, domain_nr);
+ pci_config_writel_dom(bdf, ofs + 4, ~0, domain_nr);
+ u32 high = pci_config_readl_dom(bdf, ofs + 4, domain_nr);
+ pci_config_writel_dom(bdf, ofs + 4, hold, domain_nr);
val |= ((u64)high << 32);
mask |= ((u64)0xffffffff << 32);
*psize = (~(val & mask)) + 1;
@@ -717,15 +740,20 @@ pci_bios_get_bar(struct pci_device *pci, int bar,
}
static int pci_bios_bridge_region_is64(struct pci_region *r,
- struct pci_device *pci, int type)
+ struct pci_device *pci, int type,
+ int domain_nr)
{
if (type != PCI_REGION_TYPE_PREFMEM)
return 0;
- u32 pmem = pci_config_readl(pci->bdf, PCI_PREF_MEMORY_BASE);
+ u32 pmem = pci_config_readl_dom(pci->bdf, PCI_PREF_MEMORY_BASE,
+ domain_nr);
if (!pmem) {
- pci_config_writel(pci->bdf, PCI_PREF_MEMORY_BASE, 0xfff0fff0);
- pmem = pci_config_readl(pci->bdf, PCI_PREF_MEMORY_BASE);
- pci_config_writel(pci->bdf, PCI_PREF_MEMORY_BASE, 0x0);
+ pci_config_writel_dom(pci->bdf, PCI_PREF_MEMORY_BASE, 0xfff0fff0,
+ domain_nr);
+ pmem = pci_config_readl_dom(pci->bdf, PCI_PREF_MEMORY_BASE,
+ domain_nr);
+ pci_config_writel_dom(pci->bdf, PCI_PREF_MEMORY_BASE, 0x0,
+ domain_nr);
}
if ((pmem & PCI_PREF_RANGE_TYPE_MASK) != PCI_PREF_RANGE_TYPE_64)
return 0;
@@ -801,13 +829,15 @@ pci_region_create_entry(struct pci_bus *bus, struct pci_device *dev,
return entry;
}
-static int pci_bus_hotplug_support(struct pci_bus *bus, u8 pcie_cap)
+static int pci_bus_hotplug_support(struct pci_bus *bus, u8 pcie_cap,
+ int domain_nr)
{
u8 shpc_cap;
if (pcie_cap) {
- u16 pcie_flags = pci_config_readw(bus->bus_dev->bdf,
- pcie_cap + PCI_EXP_FLAGS);
+ u16 pcie_flags = pci_config_readw_dom(bus->bus_dev->bdf,
+ pcie_cap + PCI_EXP_FLAGS,
+ domain_nr);
u8 port_type = ((pcie_flags & PCI_EXP_FLAGS_TYPE) >>
(__builtin_ffs(PCI_EXP_FLAGS_TYPE) - 1));
u8 downstream_port = (port_type == PCI_EXP_TYPE_DOWNSTREAM) ||
@@ -826,7 +856,8 @@ static int pci_bus_hotplug_support(struct pci_bus *bus, u8 pcie_cap)
return downstream_port && slot_implemented;
}
- shpc_cap = pci_find_capability(bus->bus_dev->bdf, PCI_CAP_ID_SHPC, 0);
+ shpc_cap = pci_find_capability_dom(bus->bus_dev->bdf, PCI_CAP_ID_SHPC, 0,
+ domain_nr);
return !!shpc_cap;
}
@@ -835,7 +866,8 @@ static int pci_bus_hotplug_support(struct pci_bus *bus, u8 pcie_cap)
* Note: disables bridge's window registers as a side effect.
*/
static int pci_bridge_has_region(struct pci_device *pci,
- enum pci_region_type region_type)
+ enum pci_region_type region_type,
+ int domain_nr)
{
u8 base;
@@ -851,12 +883,12 @@ static int pci_bridge_has_region(struct pci_device *pci,
return 1;
}
- pci_config_writeb(pci->bdf, base, 0xFF);
+ pci_config_writeb_dom(pci->bdf, base, 0xFF, domain_nr);
- return pci_config_readb(pci->bdf, base) != 0;
+ return pci_config_readb_dom(pci->bdf, base, domain_nr) != 0;
}
-static int pci_bios_check_devices(struct pci_bus *busses)
+static int pci_bios_check_devices(struct pci_bus *busses, int domain_nr)
{
dprintf(1, "PCI: check devices\n");
@@ -879,7 +911,7 @@ static int pci_bios_check_devices(struct pci_bus *busses)
continue;
int type, is64;
u64 size;
- pci_bios_get_bar(pci, i, &type, &size, &is64);
+ pci_bios_get_bar(pci, i, &type, &size, &is64, domain_nr);
if (size == 0)
continue;
@@ -909,14 +941,14 @@ static int pci_bios_check_devices(struct pci_bus *busses)
parent = &busses[0];
int type;
u16 bdf = s->bus_dev->bdf;
- u8 pcie_cap = pci_find_capability(bdf, PCI_CAP_ID_EXP, 0);
- u8 qemu_cap = pci_find_resource_reserve_capability(bdf);
+ u8 pcie_cap = pci_find_capability_dom(bdf, PCI_CAP_ID_EXP, 0, domain_nr);
+ u8 qemu_cap = pci_find_resource_reserve_capability(bdf, domain_nr);
- int hotplug_support = pci_bus_hotplug_support(s, pcie_cap);
+ int hotplug_support = pci_bus_hotplug_support(s, pcie_cap, domain_nr);
for (type = 0; type < PCI_REGION_TYPE_COUNT; type++) {
u64 align = (type == PCI_REGION_TYPE_IO) ?
PCI_BRIDGE_IO_MIN : PCI_BRIDGE_MEM_MIN;
- if (!pci_bridge_has_region(s->bus_dev, type))
+ if (!pci_bridge_has_region(s->bus_dev, type, domain_nr))
continue;
u64 size = 0;
if (qemu_cap) {
@@ -924,22 +956,25 @@ static int pci_bios_check_devices(struct pci_bus *busses)
u64 tmp_size_64;
switch(type) {
case PCI_REGION_TYPE_IO:
- tmp_size_64 = (pci_config_readl(bdf, qemu_cap + RES_RESERVE_IO) |
- (u64)pci_config_readl(bdf, qemu_cap + RES_RESERVE_IO + 4) << 32);
+ tmp_size_64 = (pci_config_readl_dom(bdf, qemu_cap + RES_RESERVE_IO, domain_nr) |
+ (u64)pci_config_readl_dom(bdf, qemu_cap + RES_RESERVE_IO + 4, domain_nr) << 32);
if (tmp_size_64 != (u64)-1) {
size = tmp_size_64;
}
break;
case PCI_REGION_TYPE_MEM:
- tmp_size = pci_config_readl(bdf, qemu_cap + RES_RESERVE_MEM);
+ tmp_size = pci_config_readl_dom(bdf, qemu_cap + RES_RESERVE_MEM, domain_nr);
if (tmp_size != (u32)-1) {
size = tmp_size;
}
break;
case PCI_REGION_TYPE_PREFMEM:
- tmp_size = pci_config_readl(bdf, qemu_cap + RES_RESERVE_PREF_MEM_32);
- tmp_size_64 = (pci_config_readl(bdf, qemu_cap + RES_RESERVE_PREF_MEM_64) |
- (u64)pci_config_readl(bdf, qemu_cap + RES_RESERVE_PREF_MEM_64 + 4) << 32);
+ tmp_size = pci_config_readl_dom(bdf, qemu_cap + RES_RESERVE_PREF_MEM_32,
+ domain_nr);
+ tmp_size_64 = (pci_config_readl_dom(bdf, qemu_cap + RES_RESERVE_PREF_MEM_64,
+ domain_nr) |
+ (u64)pci_config_readl_dom(bdf, qemu_cap + RES_RESERVE_PREF_MEM_64 + 4,
+ domain_nr) << 32);
if (tmp_size != (u32)-1 && tmp_size_64 == (u64)-1) {
size = tmp_size;
} else if (tmp_size == (u32)-1 && tmp_size_64 != (u64)-1) {
@@ -970,7 +1005,7 @@ static int pci_bios_check_devices(struct pci_bus *busses)
size = ALIGN(sum, align);
}
int is64 = pci_bios_bridge_region_is64(&s->r[type],
- s->bus_dev, type);
+ s->bus_dev, type, domain_nr);
// entry->bar is -1 if the entry represents a bridge region
struct pci_region_entry *entry = pci_region_create_entry(
parent, s->bus_dev, -1, size, align, type, is64);
@@ -1036,6 +1071,7 @@ static int pci_bios_init_root_regions_mem(struct pci_bus *bus)
align = pci_region_align(r_start);
r_start->base = ALIGN_DOWN((r_end->base - sum), align);
+ dprintf(1, "==============\n\nr_start->base = 0x%llx, pcimem_start = 0x%llx, pcimem_end = 0x%llx\n============\n", r_start->base, pcimem_start, pcimem_end);
if ((r_start->base < pcimem_start) ||
(r_start->base > pcimem_end))
// Memory range requested is larger than available.
@@ -1127,8 +1163,8 @@ static void pci_bios_map_devices(struct pci_bus *busses)
r64_pref.base = r64_mem.base + sum_mem;
r64_pref.base = ALIGN(r64_pref.base, align_pref);
r64_pref.base = ALIGN(r64_pref.base, (1LL<<30)); // 1G hugepage
- pcimem64_start = r64_mem.base;
- pcimem64_end = r64_pref.base + sum_pref;
+ pcimem64_start = r64_mem.base + pxb_mcfg_size;
+ pcimem64_end = r64_pref.base + sum_pref + pxb_mcfg_size;
pcimem64_end = ALIGN(pcimem64_end, (1LL<<30)); // 1G hugepage
dprintf(1, "PCI: 64: %016llx - %016llx\n", pcimem64_start, pcimem64_end);
@@ -1165,9 +1201,12 @@ pci_setup(void)
return;
}
pci_bios_init_bus();
+ /* FIXME! Hardcode is just for debugging right now */
+ pci_bios_init_pxb_bus(1);
dprintf(1, "=== PCI device probing ===\n");
- pci_probe_devices();
+ pci_probe_devices(0);
+ pci_probe_devices(1);
pcimem_start = RamSize;
pci_bios_init_platform();
@@ -1179,7 +1218,7 @@ pci_setup(void)
return;
}
memset(busses, 0, sizeof(*busses) * (MaxPCIBus + 1));
- if (pci_bios_check_devices(busses))
+ if (pci_bios_check_devices(busses, 0))
return;
dprintf(1, "=== PCI new allocation pass #2 ===\n");
@@ -1187,6 +1226,14 @@ pci_setup(void)
pci_bios_init_devices();
+ /* then check pxb host busses */
+ memset(busses, 0, sizeof(*busses) * (MaxPCIBus + 1));
+ if (pci_bios_check_devices(busses, 1))
+ return;
+
+ //pci_bios_map_devices(busses);
+ //pci_bios_init_devices();
+
free(busses);
pci_enable_default_vga();
diff --git a/src/hw/pci.c b/src/hw/pci.c
index 9855bad..cc1b6ec 100644
--- a/src/hw/pci.c
+++ b/src/hw/pci.c
@@ -11,72 +11,75 @@
#include "util.h" // udelay
#include "x86.h" // outl
-#define PORT_PCI_CMD 0x0cf8
-#define PORT_PCI_DATA 0x0cfc
-
-void pci_config_writel(u16 bdf, u32 addr, u32 val)
+void pci_config_writel_dom(u16 bdf, u32 addr, u32 val, int domain_nr)
{
- outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD);
- outl(val, PORT_PCI_DATA);
+ outl(0x80000000 | (bdf << 8) | (addr & 0xfc),
+ domain_nr ? PORT_PXB_CMD_BASE + ((domain_nr - 1) << 3) : PORT_PCI_CMD);
+ outl(val, (domain_nr ? PORT_PXB_DATA_BASE + ((domain_nr - 1) << 3) : PORT_PCI_DATA));
}
-void pci_config_writew(u16 bdf, u32 addr, u16 val)
+void pci_config_writew_dom(u16 bdf, u32 addr, u16 val, int domain_nr)
{
- outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD);
- outw(val, PORT_PCI_DATA + (addr & 2));
+ outl(0x80000000 | (bdf << 8) | (addr & 0xfc),
+ domain_nr == 0 ? PORT_PCI_CMD : PORT_PXB_CMD_BASE + (domain_nr << 3));
+ outw(val, (domain_nr ? PORT_PXB_DATA_BASE + ((domain_nr - 1) << 3) : PORT_PCI_DATA) + (addr & 2));
}
-void pci_config_writeb(u16 bdf, u32 addr, u8 val)
+void pci_config_writeb_dom(u16 bdf, u32 addr, u8 val, int domain_nr)
{
- outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD);
- outb(val, PORT_PCI_DATA + (addr & 3));
+ outl(0x80000000 | (bdf << 8) | (addr & 0xfc),
+ domain_nr ? PORT_PXB_CMD_BASE + ((domain_nr - 1) << 3) : PORT_PCI_CMD);
+ outb(val, (domain_nr ? PORT_PXB_DATA_BASE + ((domain_nr - 1) << 3) : PORT_PCI_DATA) + (addr & 3));
}
-u32 pci_config_readl(u16 bdf, u32 addr)
+u32 pci_config_readl_dom(u16 bdf, u32 addr, int domain_nr)
{
- outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD);
- return inl(PORT_PCI_DATA);
+ outl(0x80000000 | (bdf << 8) | (addr & 0xfc),
+ domain_nr ? PORT_PXB_CMD_BASE + ((domain_nr - 1) << 3) : PORT_PCI_CMD);
+ return inl((domain_nr ? PORT_PXB_DATA_BASE + ((domain_nr - 1) << 3) : PORT_PCI_DATA));
}
-u16 pci_config_readw(u16 bdf, u32 addr)
+u16 pci_config_readw_dom(u16 bdf, u32 addr, int domain_nr)
{
- outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD);
- return inw(PORT_PCI_DATA + (addr & 2));
+ outl(0x80000000 | (bdf << 8) | (addr & 0xfc),
+ domain_nr ? PORT_PXB_CMD_BASE + ((domain_nr - 1) << 3) : PORT_PCI_CMD);
+ return inw((domain_nr ? PORT_PXB_DATA_BASE + ((domain_nr - 1) << 3) : PORT_PCI_DATA) + (addr & 2));
}
-u8 pci_config_readb(u16 bdf, u32 addr)
+u8 pci_config_readb_dom(u16 bdf, u32 addr, int domain_nr)
{
- outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD);
- return inb(PORT_PCI_DATA + (addr & 3));
+ outl(0x80000000 | (bdf << 8) | (addr & 0xfc),
+ domain_nr ? PORT_PXB_CMD_BASE + ((domain_nr - 1) << 3) : PORT_PCI_CMD);
+ return inb((domain_nr ? PORT_PXB_DATA_BASE + ((domain_nr - 1) << 3) : PORT_PCI_DATA) + (addr & 3));
}
void
-pci_config_maskw(u16 bdf, u32 addr, u16 off, u16 on)
+pci_config_maskw_dom(u16 bdf, u32 addr, u16 off, u16 on, int domain_nr)
{
- u16 val = pci_config_readw(bdf, addr);
+ u16 val = pci_config_readw_dom(bdf, addr, domain_nr);
val = (val & ~off) | on;
- pci_config_writew(bdf, addr, val);
+ pci_config_writew_dom(bdf, addr, val, domain_nr);
}
-u8 pci_find_capability(u16 bdf, u8 cap_id, u8 cap)
+u8 pci_find_capability_dom(u16 bdf, u8 cap_id, u8 cap, int domain_nr)
{
int i;
- u16 status = pci_config_readw(bdf, PCI_STATUS);
+ u16 status = pci_config_readw_dom(bdf, PCI_STATUS, domain_nr);
if (!(status & PCI_STATUS_CAP_LIST))
return 0;
if (cap == 0) {
/* find first */
- cap = pci_config_readb(bdf, PCI_CAPABILITY_LIST);
+ cap = pci_config_readb_dom(bdf, PCI_CAPABILITY_LIST, domain_nr);
} else {
/* find next */
- cap = pci_config_readb(bdf, cap + PCI_CAP_LIST_NEXT);
+ cap = pci_config_readb_dom(bdf, cap + PCI_CAP_LIST_NEXT, domain_nr);
}
for (i = 0; cap && i <= 0xff; i++) {
- if (pci_config_readb(bdf, cap + PCI_CAP_LIST_ID) == cap_id)
+ if (pci_config_readb_dom(bdf, cap + PCI_CAP_LIST_ID, domain_nr) == cap_id)
return cap;
- cap = pci_config_readb(bdf, cap + PCI_CAP_LIST_NEXT);
+ cap = pci_config_readb_dom(bdf, cap + PCI_CAP_LIST_NEXT, domain_nr);
}
return 0;
@@ -84,10 +87,10 @@ u8 pci_find_capability(u16 bdf, u8 cap_id, u8 cap)
// Helper function for foreachbdf() macro - return next device
int
-pci_next(int bdf, int bus)
+pci_next_dom(int bdf, int bus, int domain_nr)
{
if (pci_bdf_to_fn(bdf) == 0
- && (pci_config_readb(bdf, PCI_HEADER_TYPE) & 0x80) == 0)
+ && (pci_config_readb_dom(bdf, PCI_HEADER_TYPE, domain_nr) & 0x80) == 0)
// Last found device wasn't a multi-function device - skip to
// the next device.
bdf += 8;
@@ -98,7 +101,7 @@ pci_next(int bdf, int bus)
if (pci_bdf_to_bus(bdf) != bus)
return -1;
- u16 v = pci_config_readw(bdf, PCI_VENDOR_ID);
+ u16 v = pci_config_readw_dom(bdf, PCI_VENDOR_ID, domain_nr);
if (v != 0x0000 && v != 0xffff)
// Device is present.
return bdf;
diff --git a/src/hw/pci.h b/src/hw/pci.h
index 2e30e28..4381563 100644
--- a/src/hw/pci.h
+++ b/src/hw/pci.h
@@ -3,7 +3,11 @@
#include "types.h" // u32
+#define PORT_PCI_CMD 0x0cf8
#define PORT_PCI_REBOOT 0x0cf9
+#define PORT_PCI_DATA 0x0cfc
+#define PORT_PXB_CMD_BASE 0x1000
+#define PORT_PXB_DATA_BASE 0x1004
static inline u8 pci_bdf_to_bus(u16 bdf) {
return bdf >> 8;
@@ -27,20 +31,34 @@ static inline u16 pci_bus_devfn_to_bdf(int bus, u16 devfn) {
return (bus << 8) | devfn;
}
-#define foreachbdf(BDF, BUS) \
- for (BDF=pci_next(pci_bus_devfn_to_bdf((BUS), 0)-1, (BUS)) \
+/* for compatibility */
+#define foreachbdf(BDF, BUS) foreachbdf_dom(BDF, BUS, 0)
+
+#define foreachbdf_dom(BDF, BUS, DOMAIN) \
+ for (BDF=pci_next_dom(pci_bus_devfn_to_bdf((BUS), 0)-1, (BUS), (DOMAIN)) \
; BDF >= 0 \
- ; BDF=pci_next(BDF, (BUS)))
+ ; BDF=pci_next_dom(BDF, (BUS), (DOMAIN)))
-void pci_config_writel(u16 bdf, u32 addr, u32 val);
-void pci_config_writew(u16 bdf, u32 addr, u16 val);
-void pci_config_writeb(u16 bdf, u32 addr, u8 val);
-u32 pci_config_readl(u16 bdf, u32 addr);
-u16 pci_config_readw(u16 bdf, u32 addr);
-u8 pci_config_readb(u16 bdf, u32 addr);
-void pci_config_maskw(u16 bdf, u32 addr, u16 off, u16 on);
-u8 pci_find_capability(u16 bdf, u8 cap_id, u8 cap);
-int pci_next(int bdf, int bus);
+#define pci_config_maskw(BDF, ADDR, OFF, ON) pci_config_maskw_dom((BDF), (ADDR), (OFF), (ON), 0)
+#define pci_find_capability(BDF, CAP_ID, CAP) pci_find_capability_dom((BDF), (CAP_ID), (CAP), 0)
+#define pci_next(BDF, BUS) pci_next_dom((BDF), (BUS), 0)
+
+#define pci_config_writel(BDF, ADDR, VAL) pci_config_writel_dom((BDF), (ADDR), (VAL), 0)
+#define pci_config_writew(BDF, ADDR, VAL) pci_config_writew_dom((BDF), (ADDR), (VAL), 0)
+#define pci_config_writeb(BDF, ADDR, VAL) pci_config_writeb_dom((BDF), (ADDR), (VAL), 0)
+#define pci_config_readl(BDF, ADDR) pci_config_readl_dom((BDF), (ADDR), 0)
+#define pci_config_readw(BDF, ADDR) pci_config_readw_dom((BDF), (ADDR), 0)
+#define pci_config_readb(BDF, ADDR) pci_config_readb_dom((BDF), (ADDR), 0)
+
+void pci_config_writel_dom(u16 bdf, u32 addr, u32 val, int domain_nr);
+void pci_config_writew_dom(u16 bdf, u32 addr, u16 val, int domain_nr);
+void pci_config_writeb_dom(u16 bdf, u32 addr, u8 val, int domain_nr);
+u32 pci_config_readl_dom(u16 bdf, u32 addr, int domain_nr);
+u16 pci_config_readw_dom(u16 bdf, u32 addr, int domain_nr);
+u8 pci_config_readb_dom(u16 bdf, u32 addr, int domain_nr);
+void pci_config_maskw_dom(u16 bdf, u32 addr, u16 off, u16 on, int domain_nr);
+u8 pci_find_capability_dom(u16 bdf, u8 cap_id, u8 cap, int domain_nr);
+int pci_next_dom(int bdf, int bus, int domain_nr);
int pci_probe_host(void);
void pci_reboot(void);
diff --git a/src/hw/pci_ids.h b/src/hw/pci_ids.h
index 35096ea..1d4ddf6 100644
--- a/src/hw/pci_ids.h
+++ b/src/hw/pci_ids.h
@@ -2263,9 +2263,10 @@
#define PCI_DEVICE_ID_KORENIX_JETCARDF0 0x1600
#define PCI_DEVICE_ID_KORENIX_JETCARDF1 0x16ff
-#define PCI_VENDOR_ID_REDHAT 0x1b36
-#define PCI_DEVICE_ID_REDHAT_ROOT_PORT 0x000C
-#define PCI_DEVICE_ID_REDHAT_PXB_HOST 0x000B
+#define PCI_VENDOR_ID_REDHAT 0x1b36
+#define PCI_DEVICE_ID_REDHAT_PXB_HOST 0x000B
+#define PCI_DEVICE_ID_REDHAT_ROOT_PORT 0x000C
+#define PCI_DEVICE_ID_REDHAT_PCIE_BRIDGE 0x000E
#define PCI_VENDOR_ID_TEKRAM 0x1de1
#define PCI_DEVICE_ID_TEKRAM_DC290 0xdc29
diff --git a/src/hw/pcidevice.c b/src/hw/pcidevice.c
index 8853cf7..ec21ec1 100644
--- a/src/hw/pcidevice.c
+++ b/src/hw/pcidevice.c
@@ -15,10 +15,11 @@
struct hlist_head PCIDevices VARVERIFY32INIT;
int MaxPCIBus VARFSEG;
+int PXBHosts VARFSEG;
// Find all PCI devices and populate PCIDevices linked list.
void
-pci_probe_devices(void)
+pci_probe_devices(int domain_nr)
{
dprintf(3, "PCI probe\n");
struct pci_device *busdevs[256];
@@ -29,7 +30,7 @@ pci_probe_devices(void)
while (bus < 0xff && (bus < MaxPCIBus || rootbuses < extraroots)) {
bus++;
int bdf;
- foreachbdf(bdf, bus) {
+ foreachbdf_dom(bdf, bus, domain_nr) {
// Create new pci_device struct and add to list.
struct pci_device *dev = malloc_tmp(sizeof(*dev));
if (!dev) {
@@ -56,6 +57,7 @@ pci_probe_devices(void)
}
// Populate pci_device info.
+ dev->domain_nr = domain_nr;
dev->bdf = bdf;
dev->parent = parent;
dev->rootbus = rootbus;
@@ -69,7 +71,7 @@ pci_probe_devices(void)
dev->header_type = pci_config_readb(bdf, PCI_HEADER_TYPE);
u8 v = dev->header_type & 0x7f;
if (v == PCI_HEADER_TYPE_BRIDGE || v == PCI_HEADER_TYPE_CARDBUS) {
- u8 secbus = pci_config_readb(bdf, PCI_SECONDARY_BUS);
+ u8 secbus = pci_config_readb_dom(bdf, PCI_SECONDARY_BUS, domain_nr);
dev->secondary_bus = secbus;
if (secbus > bus && !busdevs[secbus])
busdevs[secbus] = dev;
diff --git a/src/hw/pcidevice.h b/src/hw/pcidevice.h
index 225d545..ddf60bb 100644
--- a/src/hw/pcidevice.h
+++ b/src/hw/pcidevice.h
@@ -5,6 +5,7 @@
#include "list.h" // hlist_node
struct pci_device {
+ u32 domain_nr;
u16 bdf;
u8 rootbus;
struct hlist_node node;
@@ -22,6 +23,7 @@ struct pci_device {
};
extern struct hlist_head PCIDevices;
extern int MaxPCIBus;
+extern int PXBHosts;
static inline u32 pci_classprog(struct pci_device *pci) {
return (pci->class << 8) | pci->prog_if;
@@ -30,6 +32,12 @@ static inline u32 pci_classprog(struct pci_device *pci) {
#define foreachpci(PCI) \
hlist_for_each_entry(PCI, &PCIDevices, node)
+#define foreachpci_dom(PCI, DOMAIN) \
+ hlist_for_each_entry(PCI, &PCIDevices, node) { \
+ if (pci->domain_nr != (DOMAIN)) \
+ continue; \
+ }
+
#define PCI_ANY_ID (~0)
struct pci_device_id {
u32 vendid;
@@ -62,7 +70,7 @@ struct pci_device_id {
.vendid = 0, \
}
-void pci_probe_devices(void);
+void pci_probe_devices(int domain_nr);
struct pci_device *pci_find_device(u16 vendid, u16 devid);
struct pci_device *pci_find_class(u16 classid);
int pci_init_device(const struct pci_device_id *ids
--
2.7.4
More information about the SeaBIOS
mailing list