qemu-ppc
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-ppc] [Qemu-devel] [PATCH v5 for-2.3 22/28] hw/pci: piix - supo


From: Michael S. Tsirkin
Subject: Re: [Qemu-ppc] [Qemu-devel] [PATCH v5 for-2.3 22/28] hw/pci: piix - suport multiple host bridges
Date: Tue, 10 Mar 2015 17:22:59 +0100

On Tue, Mar 10, 2015 at 05:32:08PM +0200, Marcel Apfelbaum wrote:
> From: Marcel Apfelbaum <address@hidden>
> 
> 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 <address@hidden>
> ---
>  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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]