[SeaBIOS] [Qemu-devel] [PATCH v5 for-2.3 22/28] hw/pci: piix - suport multiple host bridges

Michael S. Tsirkin mst at redhat.com
Tue Mar 10 17:22:59 CET 2015


On Tue, Mar 10, 2015 at 05:32:08PM +0200, Marcel Apfelbaum wrote:
> From: Marcel Apfelbaum <marcel.a at redhat.com>
> 
> Instead of assuming it has only one bus, it
> enumerates all the host bridges until it finds
> the one with bus number corresponding with the
> config register.

This really only works for PXB since that listens
in on config cycles on the main bus.
Best limit to that.

One also wonders what will happen when multiple
PXBs are present on separate root complexes.

> 
> Signed-off-by: Marcel Apfelbaum <marcel at redhat.com>
> ---
>  hw/pci-host/piix.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 56 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
> index 0033ab4..3c3a192 100644
> --- a/hw/pci-host/piix.c
> +++ b/hw/pci-host/piix.c
> @@ -255,6 +255,61 @@ static void i440fx_pcihost_get_pci_hole64_end(Object *obj, Visitor *v,
>      visit_type_uint64(v, &w64.end, name, errp);
>  }
>  
> +static PCIBus *i440fx_find_primary_bus(int bus_num)
> +{
> +    PCIHostState *host;
> +    PCIBus *bus = NULL;
> +    int current = -1;
> +
> +    HOST_BRIDGE_FOREACH(host) {
> +        int b = pci_bus_num(host->bus);
> +        if (b <= bus_num && b > current) {
> +            current = b;
> +            bus = host->bus;
> +        }
> +    }
> +
> +    return bus;
> +}
> +
> +static void i440fx_pcihost_data_write(void *opaque, hwaddr addr,
> +                                      uint64_t val, unsigned len)
> +{
> +    uint32_t config_reg = PCI_HOST_BRIDGE(opaque)->config_reg;
> +
> +    if (config_reg & (1u << 31)) {
> +        int bus_num = (config_reg >> 16) & 0xFF;
> +        PCIBus *bus = i440fx_find_primary_bus(bus_num);
> +
> +        if (bus) {
> +            pci_data_write(bus, config_reg | (addr & 3), val, len);
> +        }
> +    }
> +}
> +
> +static uint64_t i440fx_pcihost_data_read(void *opaque,
> +                                         hwaddr addr, unsigned len)
> +{
> +    uint32_t config_reg = PCI_HOST_BRIDGE(opaque)->config_reg;
> +
> +    if (config_reg & (1U << 31)) {
> +        int bus_num = (config_reg >> 16) & 0xFF;
> +        PCIBus *bus = i440fx_find_primary_bus(bus_num);
> +
> +        if (bus) {
> +            return pci_data_read(bus, config_reg | (addr & 3), len);
> +        }
> +    }
> +
> +    return 0xffffffff;
> +}
> +
> +const MemoryRegionOps i440fx_pcihost_data_le_ops = {
> +    .read = i440fx_pcihost_data_read,
> +    .write = i440fx_pcihost_data_write,
> +    .endianness = DEVICE_LITTLE_ENDIAN,
> +};
> +
>  static void i440fx_pcihost_initfn(Object *obj)
>  {
>      PCIHostState *s = PCI_HOST_BRIDGE(obj);
> @@ -262,7 +317,7 @@ static void i440fx_pcihost_initfn(Object *obj)
>  
>      memory_region_init_io(&s->conf_mem, obj, &pci_host_conf_le_ops, s,
>                            "pci-conf-idx", 4);
> -    memory_region_init_io(&s->data_mem, obj, &pci_host_data_le_ops, s,
> +    memory_region_init_io(&s->data_mem, obj, &i440fx_pcihost_data_le_ops, s,
>                            "pci-conf-data", 4);
>  
>      object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_START, "int",
> -- 
> 2.1.0



More information about the SeaBIOS mailing list