#include <asm/xen/xen-ops.h>
+#include <linux/acpi.h>
#include <linux/printk.h>
+#include <linux/of_address.h>
+#include <linux/of_pci.h>
+#include <xen/xen.h>
+#include <xen/interface/physdev.h>
+#include <asm/xen/hypercall.h>
void xen_pci_register_host_bridge(struct pci_host_bridge *bridge)
{
-// struct physdev_pci_mmcfg_reserved r;
+ struct physdev_pci_mmcfg_reserved harg;
struct pci_bus *bus = bridge->bus;
+ struct device *dev = bridge->dev.parent;
+ struct resource mmio_res, busr_res;
+ int err;
- printk("============== Register Hostbridge ================\n");
+ /* XXX: Implement ACPI */
+ if (!acpi_disabled)
+ goto err;
- printk("seg %u\n", pci_domain_nr(bus));
+ /*
+ * For convience the resource 0 will always be used to fill the
+ * field 'address' of pci_mmcfg_reserved.
+ */
+ err = of_address_to_resource(dev->of_node, 0, &mmio_res);
+ if (err)
+ goto err;
- while (1);
+ /*
+ * bridge->windows should contain all the resources. However
+ * pci_register_host_register will move all the resources in a
+ * temporary list before calling pcibios_add_bus. So it is not
+ * possible to find the bus-range from that. Use the
+ * of_pci_parse_bus_range instead.
+ */
+ err = of_pci_parse_bus_range(dev->of_node, &busr_res);
+ if (err) {
+ /* XXX: Assume the bus range is 0x00 - 0xff */
+ busr_res.start = 0;
+ busr_res.end = 0xff;
+ }
+
+ harg.address = mmio_res.start;
+ harg.segment = pci_domain_nr(bus);
+ harg.start_bus = busr_res.start;
+ harg.end_bus = busr_res.end;
+ harg.flags = XEN_PCI_MMCFG_RESERVED;
+
+ err = HYPERVISOR_physdev_op(PHYSDEVOP_pci_mmcfg_reserved, &harg);
+ if ( err )
+ goto err;
+
+ return;
+
+err:
+ dev_err(dev, "xen: Failed to register hostbridge - passthrough might fail!\n");
}