From d6e65d54f0fa980f891aa3166d85b6ffd7d541eb Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Tue, 2 Oct 2012 13:21:54 -0600 Subject: pci: Helper function for testing if an INTx route changed Signed-off-by: Alex Williamson Signed-off-by: Michael S. Tsirkin --- hw/pci.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'hw/pci.c') diff --git a/hw/pci.c b/hw/pci.c index d44fd0e10a..8c6b3d19ae 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -1121,6 +1121,11 @@ PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin) return bus->route_intx_to_irq(bus->irq_opaque, pin); } +bool pci_intx_route_changed(PCIINTxRoute *old, PCIINTxRoute *new) +{ + return old->mode != new->mode || old->irq != new->irq; +} + void pci_bus_fire_intx_routing_notifier(PCIBus *bus) { PCIDevice *dev; -- cgit v1.2.3-55-g7522 From 05c0621e64b425d9f89bef542f0b85e61dc57ff8 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Wed, 17 Oct 2012 16:13:12 -0600 Subject: pci: Return PCI_INTX_DISABLED when no bus INTx routing support Rather than assert, simply return PCI_INTX_DISABLED when we don't have a pci_route_irq_fn. PIIX already returns DISABLED for an invalid pin, so users already deal with this state. Users of this interface should only be acting on an ENABLED or INVERTED return value (though we really have no support for INVERTED). Also complain loudly when we hit this so we don't forget it's missing. Signed-off-by: Alex Williamson Signed-off-by: Michael S. Tsirkin Acked-by: Jan Kiszka --- hw/pci.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'hw/pci.c') diff --git a/hw/pci.c b/hw/pci.c index 8c6b3d19ae..70b5fd965b 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -1117,7 +1117,13 @@ PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin) pin = bus->map_irq(dev, pin); dev = bus->parent_dev; } while (dev); - assert(bus->route_intx_to_irq); + + if (!bus->route_intx_to_irq) { + error_report("PCI: Bug - unimplemented PCI INTx routing (%s)\n", + object_get_typename(OBJECT(bus->qbus.parent))); + return (PCIINTxRoute) { PCI_INTX_DISABLED, -1 }; + } + return bus->route_intx_to_irq(bus->irq_opaque, pin); } -- cgit v1.2.3-55-g7522 From e26631b74663f59b5873a84ed5b92ee4ddf48255 Mon Sep 17 00:00:00 2001 From: Michael S. Tsirkin Date: Mon, 22 Oct 2012 12:35:00 +0200 Subject: pci: make each capability DWORD aligned PCI spec (see e.g. 6.7 Capabilities List in spec rev 3.0) requires that each capability is DWORD aligned. Ensure this when allocating space by rounding size up to 4. Signed-off-by: Michael S. Tsirkin --- hw/pci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'hw/pci.c') diff --git a/hw/pci.c b/hw/pci.c index 70b5fd965b..35cb374845 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -1906,7 +1906,7 @@ int pci_add_capability(PCIDevice *pdev, uint8_t cap_id, config[PCI_CAP_LIST_NEXT] = pdev->config[PCI_CAPABILITY_LIST]; pdev->config[PCI_CAPABILITY_LIST] = offset; pdev->config[PCI_STATUS] |= PCI_STATUS_CAP_LIST; - memset(pdev->used + offset, 0xFF, size); + memset(pdev->used + offset, 0xFF, QEMU_ALIGN_UP(size, 4)); /* Make capability read-only by default */ memset(pdev->wmask + offset, 0, size); /* Check capability by default */ @@ -1926,7 +1926,7 @@ void pci_del_capability(PCIDevice *pdev, uint8_t cap_id, uint8_t size) memset(pdev->w1cmask + offset, 0, size); /* Clear cmask as device-specific registers can't be checked */ memset(pdev->cmask + offset, 0, size); - memset(pdev->used + offset, 0, size); + memset(pdev->used + offset, 0, QEMU_ALIGN_UP(size, 4)); if (!pdev->config[PCI_CAPABILITY_LIST]) pdev->config[PCI_STATUS] &= ~PCI_STATUS_CAP_LIST; -- cgit v1.2.3-55-g7522 From b56d701f1d1f1828c9fabea535b3460857546dd0 Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Fri, 19 Oct 2012 16:43:28 -0400 Subject: pci: pci capability must be in PCI space pci capability must be in PCI space. It can't lay in PCIe extended config space. Reviewed-by: Paolo Bonzini Signed-off-by: Isaku Yamahata Signed-off-by: Jason Baron Signed-off-by: Michael S. Tsirkin --- hw/pci.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'hw/pci.c') diff --git a/hw/pci.c b/hw/pci.c index 35cb374845..82c971a17d 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -1678,16 +1678,16 @@ PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name) return pci_create_simple_multifunction(bus, devfn, false, name); } -static int pci_find_space(PCIDevice *pdev, uint8_t size) +static uint8_t pci_find_space(PCIDevice *pdev, uint8_t size) { - int config_size = pci_config_size(pdev); int offset = PCI_CONFIG_HEADER_SIZE; int i; - for (i = PCI_CONFIG_HEADER_SIZE; i < config_size; ++i) + for (i = PCI_CONFIG_HEADER_SIZE; i < PCI_CONFIG_SPACE_SIZE; ++i) { if (pdev->used[i]) offset = i + 1; else if (i - offset + 1 == size) return offset; + } return 0; } -- cgit v1.2.3-55-g7522 From 91e5615984c1fd5674caad343e750bb5ecd17995 Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Fri, 19 Oct 2012 16:43:28 -0400 Subject: pci: introduce pci_swizzle_map_irq_fn() for standardized interrupt pin swizzle Introduce pci_swizzle_map_irq_fn() for interrupt pin swizzle which is standardized. PCI bridge swizzle is common logic, by introducing this function duplicated swizzle logic will be avoided later. [jbaron@redhat.com: drop opaque argument] Reviewed-by: Paolo Bonzini Signed-off-by: Isaku Yamahata Signed-off-by: Jason Baron Signed-off-by: Michael S. Tsirkin --- hw/pci.c | 18 ++++++++++++++++++ hw/pci.h | 2 ++ 2 files changed, 20 insertions(+) (limited to 'hw/pci.c') diff --git a/hw/pci.c b/hw/pci.c index 82c971a17d..63b1857f88 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -1155,6 +1155,24 @@ void pci_device_set_intx_routing_notifier(PCIDevice *dev, dev->intx_routing_notifier = notifier; } +/* + * PCI-to-PCI bridge specification + * 9.1: Interrupt routing. Table 9-1 + * + * the PCI Express Base Specification, Revision 2.1 + * 2.2.8.1: INTx interrutp signaling - Rules + * the Implementation Note + * Table 2-20 + */ +/* + * 0 <= pin <= 3 0 = INTA, 1 = INTB, 2 = INTC, 3 = INTD + * 0-origin unlike PCI interrupt pin register. + */ +int pci_swizzle_map_irq_fn(PCIDevice *pci_dev, int pin) +{ + return (pin + PCI_SLOT(pci_dev->devfn)) % PCI_NUM_PINS; +} + /***********************************************************/ /* monitor info on PCI */ diff --git a/hw/pci.h b/hw/pci.h index a852941a5c..241c1d8905 100644 --- a/hw/pci.h +++ b/hw/pci.h @@ -318,6 +318,8 @@ void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, void *irq_opaque, int nirq); int pci_bus_get_irq_level(PCIBus *bus, int irq_num); void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *dev); +/* 0 <= pin <= 3 0 = INTA, 1 = INTB, 2 = INTC, 3 = INTD */ +int pci_swizzle_map_irq_fn(PCIDevice *pci_dev, int pin); PCIBus *pci_register_bus(DeviceState *parent, const char *name, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, void *irq_opaque, -- cgit v1.2.3-55-g7522 From f7748569902f4854ac1223c143edbde4f588040f Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Fri, 19 Oct 2012 16:43:31 -0400 Subject: pci: Add class 0xc05 as 'SMBus' [jbaron@redhat.com: add PCI_CLASS_SERIAL_SMBUS definition] Reviewed-by: Paolo Bonzini Signed-off-by: Jan Kiszka Signed-off-by: Jason Baron Signed-off-by: Michael S. Tsirkin --- hw/pci.c | 1 + hw/pci_ids.h | 1 + 2 files changed, 2 insertions(+) (limited to 'hw/pci.c') diff --git a/hw/pci.c b/hw/pci.c index 63b1857f88..dceda0bdc5 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -1237,6 +1237,7 @@ static const pci_class_desc pci_class_descriptions[] = { 0x0c02, "SSA controller", "ssa"}, { 0x0c03, "USB controller", "usb"}, { 0x0c04, "Fibre channel controller", "fibre-channel"}, + { 0x0c05, "SMBus"}, { 0, NULL} }; diff --git a/hw/pci_ids.h b/hw/pci_ids.h index 0bfc28f7fb..41f3570fb9 100644 --- a/hw/pci_ids.h +++ b/hw/pci_ids.h @@ -31,6 +31,7 @@ #define PCI_CLASS_SYSTEM_OTHER 0x0880 #define PCI_CLASS_SERIAL_USB 0x0c03 +#define PCI_CLASS_SERIAL_SMBUS 0x0c05 #define PCI_CLASS_BRIDGE_HOST 0x0600 #define PCI_CLASS_BRIDGE_ISA 0x0601 -- cgit v1.2.3-55-g7522