1315a1350SMichael S. Tsirkin /* 2315a1350SMichael S. Tsirkin * QEMU PCI bus manager 3315a1350SMichael S. Tsirkin * 4315a1350SMichael S. Tsirkin * Copyright (c) 2004 Fabrice Bellard 5315a1350SMichael S. Tsirkin * 6315a1350SMichael S. Tsirkin * Permission is hereby granted, free of charge, to any person obtaining a copy 7315a1350SMichael S. Tsirkin * of this software and associated documentation files (the "Software"), to deal 8315a1350SMichael S. Tsirkin * in the Software without restriction, including without limitation the rights 9315a1350SMichael S. Tsirkin * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10315a1350SMichael S. Tsirkin * copies of the Software, and to permit persons to whom the Software is 11315a1350SMichael S. Tsirkin * furnished to do so, subject to the following conditions: 12315a1350SMichael S. Tsirkin * 13315a1350SMichael S. Tsirkin * The above copyright notice and this permission notice shall be included in 14315a1350SMichael S. Tsirkin * all copies or substantial portions of the Software. 15315a1350SMichael S. Tsirkin * 16315a1350SMichael S. Tsirkin * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17315a1350SMichael S. Tsirkin * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18315a1350SMichael S. Tsirkin * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19315a1350SMichael S. Tsirkin * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20315a1350SMichael S. Tsirkin * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21315a1350SMichael S. Tsirkin * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22315a1350SMichael S. Tsirkin * THE SOFTWARE. 23315a1350SMichael S. Tsirkin */ 24c759b24fSMichael S. Tsirkin #include "hw/hw.h" 25c759b24fSMichael S. Tsirkin #include "hw/pci/pci.h" 26c759b24fSMichael S. Tsirkin #include "hw/pci/pci_bridge.h" 2706aac7bdSMichael S. Tsirkin #include "hw/pci/pci_bus.h" 28568f0690SDavid Gibson #include "hw/pci/pci_host.h" 2983c9089eSPaolo Bonzini #include "monitor/monitor.h" 301422e32dSPaolo Bonzini #include "net/net.h" 319c17d615SPaolo Bonzini #include "sysemu/sysemu.h" 32c759b24fSMichael S. Tsirkin #include "hw/loader.h" 33d49b6836SMarkus Armbruster #include "qemu/error-report.h" 341de7afc9SPaolo Bonzini #include "qemu/range.h" 35315a1350SMichael S. Tsirkin #include "qmp-commands.h" 367828d750SDon Koch #include "trace.h" 37c759b24fSMichael S. Tsirkin #include "hw/pci/msi.h" 38c759b24fSMichael S. Tsirkin #include "hw/pci/msix.h" 39022c62cbSPaolo Bonzini #include "exec/address-spaces.h" 405e954943SIgor Mammedov #include "hw/hotplug.h" 41e4024630SLaurent Vivier #include "hw/boards.h" 42315a1350SMichael S. Tsirkin 43315a1350SMichael S. Tsirkin //#define DEBUG_PCI 44315a1350SMichael S. Tsirkin #ifdef DEBUG_PCI 45315a1350SMichael S. Tsirkin # define PCI_DPRINTF(format, ...) printf(format, ## __VA_ARGS__) 46315a1350SMichael S. Tsirkin #else 47315a1350SMichael S. Tsirkin # define PCI_DPRINTF(format, ...) do { } while (0) 48315a1350SMichael S. Tsirkin #endif 49315a1350SMichael S. Tsirkin 50315a1350SMichael S. Tsirkin static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent); 51315a1350SMichael S. Tsirkin static char *pcibus_get_dev_path(DeviceState *dev); 52315a1350SMichael S. Tsirkin static char *pcibus_get_fw_dev_path(DeviceState *dev); 53dcc20931SPaolo Bonzini static void pcibus_reset(BusState *qbus); 54315a1350SMichael S. Tsirkin 55315a1350SMichael S. Tsirkin static Property pci_props[] = { 56315a1350SMichael S. Tsirkin DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1), 57315a1350SMichael S. Tsirkin DEFINE_PROP_STRING("romfile", PCIDevice, romfile), 58315a1350SMichael S. Tsirkin DEFINE_PROP_UINT32("rombar", PCIDevice, rom_bar, 1), 59315a1350SMichael S. Tsirkin DEFINE_PROP_BIT("multifunction", PCIDevice, cap_present, 60315a1350SMichael S. Tsirkin QEMU_PCI_CAP_MULTIFUNCTION_BITNR, false), 61315a1350SMichael S. Tsirkin DEFINE_PROP_BIT("command_serr_enable", PCIDevice, cap_present, 62315a1350SMichael S. Tsirkin QEMU_PCI_CAP_SERR_BITNR, true), 63315a1350SMichael S. Tsirkin DEFINE_PROP_END_OF_LIST() 64315a1350SMichael S. Tsirkin }; 65315a1350SMichael S. Tsirkin 66d2f69df7SBandan Das static const VMStateDescription vmstate_pcibus = { 67d2f69df7SBandan Das .name = "PCIBUS", 68d2f69df7SBandan Das .version_id = 1, 69d2f69df7SBandan Das .minimum_version_id = 1, 70d2f69df7SBandan Das .fields = (VMStateField[]) { 71d2f69df7SBandan Das VMSTATE_INT32_EQUAL(nirq, PCIBus), 72d2f69df7SBandan Das VMSTATE_VARRAY_INT32(irq_count, PCIBus, 73d2f69df7SBandan Das nirq, 0, vmstate_info_int32, 74d2f69df7SBandan Das int32_t), 75d2f69df7SBandan Das VMSTATE_END_OF_LIST() 76d2f69df7SBandan Das } 77d2f69df7SBandan Das }; 78d2f69df7SBandan Das 79d2f69df7SBandan Das static void pci_bus_realize(BusState *qbus, Error **errp) 80d2f69df7SBandan Das { 81d2f69df7SBandan Das PCIBus *bus = PCI_BUS(qbus); 82d2f69df7SBandan Das 83d2f69df7SBandan Das vmstate_register(NULL, -1, &vmstate_pcibus, bus); 84d2f69df7SBandan Das } 85d2f69df7SBandan Das 86d2f69df7SBandan Das static void pci_bus_unrealize(BusState *qbus, Error **errp) 87d2f69df7SBandan Das { 88d2f69df7SBandan Das PCIBus *bus = PCI_BUS(qbus); 89d2f69df7SBandan Das 90d2f69df7SBandan Das vmstate_unregister(NULL, &vmstate_pcibus, bus); 91d2f69df7SBandan Das } 92d2f69df7SBandan Das 93ce6a28eeSMarcel Apfelbaum static bool pcibus_is_root(PCIBus *bus) 94ce6a28eeSMarcel Apfelbaum { 95ce6a28eeSMarcel Apfelbaum return !bus->parent_dev; 96ce6a28eeSMarcel Apfelbaum } 97ce6a28eeSMarcel Apfelbaum 98602141d9SMarcel Apfelbaum static int pcibus_num(PCIBus *bus) 99602141d9SMarcel Apfelbaum { 100602141d9SMarcel Apfelbaum if (pcibus_is_root(bus)) { 101602141d9SMarcel Apfelbaum return 0; /* pci host bridge */ 102602141d9SMarcel Apfelbaum } 103602141d9SMarcel Apfelbaum return bus->parent_dev->config[PCI_SECONDARY_BUS]; 104602141d9SMarcel Apfelbaum } 105602141d9SMarcel Apfelbaum 1066a3042b2SMarcel Apfelbaum static uint16_t pcibus_numa_node(PCIBus *bus) 1076a3042b2SMarcel Apfelbaum { 1086a3042b2SMarcel Apfelbaum return NUMA_NODE_UNASSIGNED; 1096a3042b2SMarcel Apfelbaum } 1106a3042b2SMarcel Apfelbaum 111315a1350SMichael S. Tsirkin static void pci_bus_class_init(ObjectClass *klass, void *data) 112315a1350SMichael S. Tsirkin { 113315a1350SMichael S. Tsirkin BusClass *k = BUS_CLASS(klass); 114ce6a28eeSMarcel Apfelbaum PCIBusClass *pbc = PCI_BUS_CLASS(klass); 115315a1350SMichael S. Tsirkin 116315a1350SMichael S. Tsirkin k->print_dev = pcibus_dev_print; 117315a1350SMichael S. Tsirkin k->get_dev_path = pcibus_get_dev_path; 118315a1350SMichael S. Tsirkin k->get_fw_dev_path = pcibus_get_fw_dev_path; 119d2f69df7SBandan Das k->realize = pci_bus_realize; 120d2f69df7SBandan Das k->unrealize = pci_bus_unrealize; 121315a1350SMichael S. Tsirkin k->reset = pcibus_reset; 122ce6a28eeSMarcel Apfelbaum 123ce6a28eeSMarcel Apfelbaum pbc->is_root = pcibus_is_root; 124602141d9SMarcel Apfelbaum pbc->bus_num = pcibus_num; 1256a3042b2SMarcel Apfelbaum pbc->numa_node = pcibus_numa_node; 126315a1350SMichael S. Tsirkin } 127315a1350SMichael S. Tsirkin 128315a1350SMichael S. Tsirkin static const TypeInfo pci_bus_info = { 129315a1350SMichael S. Tsirkin .name = TYPE_PCI_BUS, 130315a1350SMichael S. Tsirkin .parent = TYPE_BUS, 131315a1350SMichael S. Tsirkin .instance_size = sizeof(PCIBus), 132ce6a28eeSMarcel Apfelbaum .class_size = sizeof(PCIBusClass), 133315a1350SMichael S. Tsirkin .class_init = pci_bus_class_init, 134315a1350SMichael S. Tsirkin }; 135315a1350SMichael S. Tsirkin 1363a861c46SAlex Williamson static const TypeInfo pcie_bus_info = { 1373a861c46SAlex Williamson .name = TYPE_PCIE_BUS, 1383a861c46SAlex Williamson .parent = TYPE_PCI_BUS, 1393a861c46SAlex Williamson }; 1403a861c46SAlex Williamson 141315a1350SMichael S. Tsirkin static PCIBus *pci_find_bus_nr(PCIBus *bus, int bus_num); 142315a1350SMichael S. Tsirkin static void pci_update_mappings(PCIDevice *d); 143d98f08f5SMarcel Apfelbaum static void pci_irq_handler(void *opaque, int irq_num, int level); 144133e9b22SMarkus Armbruster static void pci_add_option_rom(PCIDevice *pdev, bool is_default_rom, Error **); 145315a1350SMichael S. Tsirkin static void pci_del_option_rom(PCIDevice *pdev); 146315a1350SMichael S. Tsirkin 147315a1350SMichael S. Tsirkin static uint16_t pci_default_sub_vendor_id = PCI_SUBVENDOR_ID_REDHAT_QUMRANET; 148315a1350SMichael S. Tsirkin static uint16_t pci_default_sub_device_id = PCI_SUBDEVICE_ID_QEMU; 149315a1350SMichael S. Tsirkin 1507588e2b0SDavid Gibson static QLIST_HEAD(, PCIHostState) pci_host_bridges; 151315a1350SMichael S. Tsirkin 152cf8c704dSMichael Roth int pci_bar(PCIDevice *d, int reg) 153315a1350SMichael S. Tsirkin { 154315a1350SMichael S. Tsirkin uint8_t type; 155315a1350SMichael S. Tsirkin 156315a1350SMichael S. Tsirkin if (reg != PCI_ROM_SLOT) 157315a1350SMichael S. Tsirkin return PCI_BASE_ADDRESS_0 + reg * 4; 158315a1350SMichael S. Tsirkin 159315a1350SMichael S. Tsirkin type = d->config[PCI_HEADER_TYPE] & ~PCI_HEADER_TYPE_MULTI_FUNCTION; 160315a1350SMichael S. Tsirkin return type == PCI_HEADER_TYPE_BRIDGE ? PCI_ROM_ADDRESS1 : PCI_ROM_ADDRESS; 161315a1350SMichael S. Tsirkin } 162315a1350SMichael S. Tsirkin 163315a1350SMichael S. Tsirkin static inline int pci_irq_state(PCIDevice *d, int irq_num) 164315a1350SMichael S. Tsirkin { 165315a1350SMichael S. Tsirkin return (d->irq_state >> irq_num) & 0x1; 166315a1350SMichael S. Tsirkin } 167315a1350SMichael S. Tsirkin 168315a1350SMichael S. Tsirkin static inline void pci_set_irq_state(PCIDevice *d, int irq_num, int level) 169315a1350SMichael S. Tsirkin { 170315a1350SMichael S. Tsirkin d->irq_state &= ~(0x1 << irq_num); 171315a1350SMichael S. Tsirkin d->irq_state |= level << irq_num; 172315a1350SMichael S. Tsirkin } 173315a1350SMichael S. Tsirkin 174315a1350SMichael S. Tsirkin static void pci_change_irq_level(PCIDevice *pci_dev, int irq_num, int change) 175315a1350SMichael S. Tsirkin { 176315a1350SMichael S. Tsirkin PCIBus *bus; 177315a1350SMichael S. Tsirkin for (;;) { 178315a1350SMichael S. Tsirkin bus = pci_dev->bus; 179315a1350SMichael S. Tsirkin irq_num = bus->map_irq(pci_dev, irq_num); 180315a1350SMichael S. Tsirkin if (bus->set_irq) 181315a1350SMichael S. Tsirkin break; 182315a1350SMichael S. Tsirkin pci_dev = bus->parent_dev; 183315a1350SMichael S. Tsirkin } 184315a1350SMichael S. Tsirkin bus->irq_count[irq_num] += change; 185315a1350SMichael S. Tsirkin bus->set_irq(bus->irq_opaque, irq_num, bus->irq_count[irq_num] != 0); 186315a1350SMichael S. Tsirkin } 187315a1350SMichael S. Tsirkin 188315a1350SMichael S. Tsirkin int pci_bus_get_irq_level(PCIBus *bus, int irq_num) 189315a1350SMichael S. Tsirkin { 190315a1350SMichael S. Tsirkin assert(irq_num >= 0); 191315a1350SMichael S. Tsirkin assert(irq_num < bus->nirq); 192315a1350SMichael S. Tsirkin return !!bus->irq_count[irq_num]; 193315a1350SMichael S. Tsirkin } 194315a1350SMichael S. Tsirkin 195315a1350SMichael S. Tsirkin /* Update interrupt status bit in config space on interrupt 196315a1350SMichael S. Tsirkin * state change. */ 197315a1350SMichael S. Tsirkin static void pci_update_irq_status(PCIDevice *dev) 198315a1350SMichael S. Tsirkin { 199315a1350SMichael S. Tsirkin if (dev->irq_state) { 200315a1350SMichael S. Tsirkin dev->config[PCI_STATUS] |= PCI_STATUS_INTERRUPT; 201315a1350SMichael S. Tsirkin } else { 202315a1350SMichael S. Tsirkin dev->config[PCI_STATUS] &= ~PCI_STATUS_INTERRUPT; 203315a1350SMichael S. Tsirkin } 204315a1350SMichael S. Tsirkin } 205315a1350SMichael S. Tsirkin 206315a1350SMichael S. Tsirkin void pci_device_deassert_intx(PCIDevice *dev) 207315a1350SMichael S. Tsirkin { 208315a1350SMichael S. Tsirkin int i; 209315a1350SMichael S. Tsirkin for (i = 0; i < PCI_NUM_PINS; ++i) { 210d98f08f5SMarcel Apfelbaum pci_irq_handler(dev, i, 0); 211315a1350SMichael S. Tsirkin } 212315a1350SMichael S. Tsirkin } 213315a1350SMichael S. Tsirkin 214dcc20931SPaolo Bonzini static void pci_do_device_reset(PCIDevice *dev) 215315a1350SMichael S. Tsirkin { 216315a1350SMichael S. Tsirkin int r; 217315a1350SMichael S. Tsirkin 218315a1350SMichael S. Tsirkin pci_device_deassert_intx(dev); 21958b59014SCole Robinson assert(dev->irq_state == 0); 22058b59014SCole Robinson 221315a1350SMichael S. Tsirkin /* Clear all writable bits */ 222315a1350SMichael S. Tsirkin pci_word_test_and_clear_mask(dev->config + PCI_COMMAND, 223315a1350SMichael S. Tsirkin pci_get_word(dev->wmask + PCI_COMMAND) | 224315a1350SMichael S. Tsirkin pci_get_word(dev->w1cmask + PCI_COMMAND)); 225315a1350SMichael S. Tsirkin pci_word_test_and_clear_mask(dev->config + PCI_STATUS, 226315a1350SMichael S. Tsirkin pci_get_word(dev->wmask + PCI_STATUS) | 227315a1350SMichael S. Tsirkin pci_get_word(dev->w1cmask + PCI_STATUS)); 228315a1350SMichael S. Tsirkin dev->config[PCI_CACHE_LINE_SIZE] = 0x0; 229315a1350SMichael S. Tsirkin dev->config[PCI_INTERRUPT_LINE] = 0x0; 230315a1350SMichael S. Tsirkin for (r = 0; r < PCI_NUM_REGIONS; ++r) { 231315a1350SMichael S. Tsirkin PCIIORegion *region = &dev->io_regions[r]; 232315a1350SMichael S. Tsirkin if (!region->size) { 233315a1350SMichael S. Tsirkin continue; 234315a1350SMichael S. Tsirkin } 235315a1350SMichael S. Tsirkin 236315a1350SMichael S. Tsirkin if (!(region->type & PCI_BASE_ADDRESS_SPACE_IO) && 237315a1350SMichael S. Tsirkin region->type & PCI_BASE_ADDRESS_MEM_TYPE_64) { 238315a1350SMichael S. Tsirkin pci_set_quad(dev->config + pci_bar(dev, r), region->type); 239315a1350SMichael S. Tsirkin } else { 240315a1350SMichael S. Tsirkin pci_set_long(dev->config + pci_bar(dev, r), region->type); 241315a1350SMichael S. Tsirkin } 242315a1350SMichael S. Tsirkin } 243315a1350SMichael S. Tsirkin pci_update_mappings(dev); 244315a1350SMichael S. Tsirkin 245315a1350SMichael S. Tsirkin msi_reset(dev); 246315a1350SMichael S. Tsirkin msix_reset(dev); 247315a1350SMichael S. Tsirkin } 248315a1350SMichael S. Tsirkin 249315a1350SMichael S. Tsirkin /* 250dcc20931SPaolo Bonzini * This function is called on #RST and FLR. 251dcc20931SPaolo Bonzini * FLR if PCI_EXP_DEVCTL_BCR_FLR is set 252315a1350SMichael S. Tsirkin */ 253dcc20931SPaolo Bonzini void pci_device_reset(PCIDevice *dev) 254dcc20931SPaolo Bonzini { 255dcc20931SPaolo Bonzini qdev_reset_all(&dev->qdev); 256dcc20931SPaolo Bonzini pci_do_device_reset(dev); 257dcc20931SPaolo Bonzini } 258dcc20931SPaolo Bonzini 259dcc20931SPaolo Bonzini /* 260dcc20931SPaolo Bonzini * Trigger pci bus reset under a given bus. 261dcc20931SPaolo Bonzini * Called via qbus_reset_all on RST# assert, after the devices 262dcc20931SPaolo Bonzini * have been reset qdev_reset_all-ed already. 263dcc20931SPaolo Bonzini */ 264dcc20931SPaolo Bonzini static void pcibus_reset(BusState *qbus) 265315a1350SMichael S. Tsirkin { 26681e3e75bSPaolo Bonzini PCIBus *bus = DO_UPCAST(PCIBus, qbus, qbus); 267315a1350SMichael S. Tsirkin int i; 268315a1350SMichael S. Tsirkin 269315a1350SMichael S. Tsirkin for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) { 270315a1350SMichael S. Tsirkin if (bus->devices[i]) { 271dcc20931SPaolo Bonzini pci_do_device_reset(bus->devices[i]); 272315a1350SMichael S. Tsirkin } 273315a1350SMichael S. Tsirkin } 274315a1350SMichael S. Tsirkin 2759bdbbfc3SPaolo Bonzini for (i = 0; i < bus->nirq; i++) { 2769bdbbfc3SPaolo Bonzini assert(bus->irq_count[i] == 0); 2779bdbbfc3SPaolo Bonzini } 278315a1350SMichael S. Tsirkin } 279315a1350SMichael S. Tsirkin 2807588e2b0SDavid Gibson static void pci_host_bus_register(PCIBus *bus, DeviceState *parent) 281315a1350SMichael S. Tsirkin { 2827588e2b0SDavid Gibson PCIHostState *host_bridge = PCI_HOST_BRIDGE(parent); 2837588e2b0SDavid Gibson 2847588e2b0SDavid Gibson QLIST_INSERT_HEAD(&pci_host_bridges, host_bridge, next); 285315a1350SMichael S. Tsirkin } 286315a1350SMichael S. Tsirkin 2871ef7a2a2SDavid Gibson PCIBus *pci_find_primary_bus(void) 288315a1350SMichael S. Tsirkin { 2899bc47305SDavid Gibson PCIBus *primary_bus = NULL; 2907588e2b0SDavid Gibson PCIHostState *host; 291315a1350SMichael S. Tsirkin 2927588e2b0SDavid Gibson QLIST_FOREACH(host, &pci_host_bridges, next) { 2939bc47305SDavid Gibson if (primary_bus) { 2949bc47305SDavid Gibson /* We have multiple root buses, refuse to select a primary */ 295315a1350SMichael S. Tsirkin return NULL; 296315a1350SMichael S. Tsirkin } 2979bc47305SDavid Gibson primary_bus = host->bus; 298315a1350SMichael S. Tsirkin } 299315a1350SMichael S. Tsirkin 3009bc47305SDavid Gibson return primary_bus; 301315a1350SMichael S. Tsirkin } 302315a1350SMichael S. Tsirkin 303c473d18dSDavid Gibson PCIBus *pci_device_root_bus(const PCIDevice *d) 304315a1350SMichael S. Tsirkin { 305c473d18dSDavid Gibson PCIBus *bus = d->bus; 306315a1350SMichael S. Tsirkin 307ce6a28eeSMarcel Apfelbaum while (!pci_bus_is_root(bus)) { 308ce6a28eeSMarcel Apfelbaum d = bus->parent_dev; 309ce6a28eeSMarcel Apfelbaum assert(d != NULL); 310ce6a28eeSMarcel Apfelbaum 311315a1350SMichael S. Tsirkin bus = d->bus; 312315a1350SMichael S. Tsirkin } 313315a1350SMichael S. Tsirkin 314c473d18dSDavid Gibson return bus; 315315a1350SMichael S. Tsirkin } 316315a1350SMichael S. Tsirkin 317568f0690SDavid Gibson const char *pci_root_bus_path(PCIDevice *dev) 318c473d18dSDavid Gibson { 319568f0690SDavid Gibson PCIBus *rootbus = pci_device_root_bus(dev); 320568f0690SDavid Gibson PCIHostState *host_bridge = PCI_HOST_BRIDGE(rootbus->qbus.parent); 321568f0690SDavid Gibson PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_GET_CLASS(host_bridge); 322c473d18dSDavid Gibson 323568f0690SDavid Gibson assert(host_bridge->bus == rootbus); 324568f0690SDavid Gibson 325568f0690SDavid Gibson if (hc->root_bus_path) { 326568f0690SDavid Gibson return (*hc->root_bus_path)(host_bridge, rootbus); 327315a1350SMichael S. Tsirkin } 328315a1350SMichael S. Tsirkin 329568f0690SDavid Gibson return rootbus->qbus.name; 330315a1350SMichael S. Tsirkin } 331315a1350SMichael S. Tsirkin 3324fec6404SPaolo Bonzini static void pci_bus_init(PCIBus *bus, DeviceState *parent, 333315a1350SMichael S. Tsirkin const char *name, 334315a1350SMichael S. Tsirkin MemoryRegion *address_space_mem, 335315a1350SMichael S. Tsirkin MemoryRegion *address_space_io, 336315a1350SMichael S. Tsirkin uint8_t devfn_min) 337315a1350SMichael S. Tsirkin { 338315a1350SMichael S. Tsirkin assert(PCI_FUNC(devfn_min) == 0); 339315a1350SMichael S. Tsirkin bus->devfn_min = devfn_min; 340315a1350SMichael S. Tsirkin bus->address_space_mem = address_space_mem; 341315a1350SMichael S. Tsirkin bus->address_space_io = address_space_io; 342315a1350SMichael S. Tsirkin 343315a1350SMichael S. Tsirkin /* host bridge */ 344315a1350SMichael S. Tsirkin QLIST_INIT(&bus->child); 3452b8cc89aSDavid Gibson 3467588e2b0SDavid Gibson pci_host_bus_register(bus, parent); 347315a1350SMichael S. Tsirkin } 348315a1350SMichael S. Tsirkin 3498c0bf9e2SAlex Williamson bool pci_bus_is_express(PCIBus *bus) 3508c0bf9e2SAlex Williamson { 3518c0bf9e2SAlex Williamson return object_dynamic_cast(OBJECT(bus), TYPE_PCIE_BUS); 3528c0bf9e2SAlex Williamson } 3538c0bf9e2SAlex Williamson 3540889464aSAlex Williamson bool pci_bus_is_root(PCIBus *bus) 3550889464aSAlex Williamson { 356ce6a28eeSMarcel Apfelbaum return PCI_BUS_GET_CLASS(bus)->is_root(bus); 3570889464aSAlex Williamson } 3580889464aSAlex Williamson 359dd301ca6SAndreas Färber void pci_bus_new_inplace(PCIBus *bus, size_t bus_size, DeviceState *parent, 3604fec6404SPaolo Bonzini const char *name, 3614fec6404SPaolo Bonzini MemoryRegion *address_space_mem, 3624fec6404SPaolo Bonzini MemoryRegion *address_space_io, 36360a0e443SAlex Williamson uint8_t devfn_min, const char *typename) 3644fec6404SPaolo Bonzini { 365fb17dfe0SAndreas Färber qbus_create_inplace(bus, bus_size, typename, parent, name); 3664fec6404SPaolo Bonzini pci_bus_init(bus, parent, name, address_space_mem, 3674fec6404SPaolo Bonzini address_space_io, devfn_min); 3684fec6404SPaolo Bonzini } 3694fec6404SPaolo Bonzini 370315a1350SMichael S. Tsirkin PCIBus *pci_bus_new(DeviceState *parent, const char *name, 371315a1350SMichael S. Tsirkin MemoryRegion *address_space_mem, 372315a1350SMichael S. Tsirkin MemoryRegion *address_space_io, 37360a0e443SAlex Williamson uint8_t devfn_min, const char *typename) 374315a1350SMichael S. Tsirkin { 375315a1350SMichael S. Tsirkin PCIBus *bus; 376315a1350SMichael S. Tsirkin 37760a0e443SAlex Williamson bus = PCI_BUS(qbus_create(typename, parent, name)); 3784fec6404SPaolo Bonzini pci_bus_init(bus, parent, name, address_space_mem, 379315a1350SMichael S. Tsirkin address_space_io, devfn_min); 380315a1350SMichael S. Tsirkin return bus; 381315a1350SMichael S. Tsirkin } 382315a1350SMichael S. Tsirkin 383315a1350SMichael S. Tsirkin void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, 384315a1350SMichael S. Tsirkin void *irq_opaque, int nirq) 385315a1350SMichael S. Tsirkin { 386315a1350SMichael S. Tsirkin bus->set_irq = set_irq; 387315a1350SMichael S. Tsirkin bus->map_irq = map_irq; 388315a1350SMichael S. Tsirkin bus->irq_opaque = irq_opaque; 389315a1350SMichael S. Tsirkin bus->nirq = nirq; 390315a1350SMichael S. Tsirkin bus->irq_count = g_malloc0(nirq * sizeof(bus->irq_count[0])); 391315a1350SMichael S. Tsirkin } 392315a1350SMichael S. Tsirkin 393315a1350SMichael S. Tsirkin PCIBus *pci_register_bus(DeviceState *parent, const char *name, 394315a1350SMichael S. Tsirkin pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, 395315a1350SMichael S. Tsirkin void *irq_opaque, 396315a1350SMichael S. Tsirkin MemoryRegion *address_space_mem, 397315a1350SMichael S. Tsirkin MemoryRegion *address_space_io, 39860a0e443SAlex Williamson uint8_t devfn_min, int nirq, const char *typename) 399315a1350SMichael S. Tsirkin { 400315a1350SMichael S. Tsirkin PCIBus *bus; 401315a1350SMichael S. Tsirkin 402315a1350SMichael S. Tsirkin bus = pci_bus_new(parent, name, address_space_mem, 40360a0e443SAlex Williamson address_space_io, devfn_min, typename); 404315a1350SMichael S. Tsirkin pci_bus_irqs(bus, set_irq, map_irq, irq_opaque, nirq); 405315a1350SMichael S. Tsirkin return bus; 406315a1350SMichael S. Tsirkin } 407315a1350SMichael S. Tsirkin 408315a1350SMichael S. Tsirkin int pci_bus_num(PCIBus *s) 409315a1350SMichael S. Tsirkin { 410602141d9SMarcel Apfelbaum return PCI_BUS_GET_CLASS(s)->bus_num(s); 411315a1350SMichael S. Tsirkin } 412315a1350SMichael S. Tsirkin 4136a3042b2SMarcel Apfelbaum int pci_bus_numa_node(PCIBus *bus) 4146a3042b2SMarcel Apfelbaum { 4156a3042b2SMarcel Apfelbaum return PCI_BUS_GET_CLASS(bus)->numa_node(bus); 416315a1350SMichael S. Tsirkin } 417315a1350SMichael S. Tsirkin 418315a1350SMichael S. Tsirkin static int get_pci_config_device(QEMUFile *f, void *pv, size_t size) 419315a1350SMichael S. Tsirkin { 420315a1350SMichael S. Tsirkin PCIDevice *s = container_of(pv, PCIDevice, config); 421e78e9ae4SDon Koch PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(s); 422315a1350SMichael S. Tsirkin uint8_t *config; 423315a1350SMichael S. Tsirkin int i; 424315a1350SMichael S. Tsirkin 425315a1350SMichael S. Tsirkin assert(size == pci_config_size(s)); 426315a1350SMichael S. Tsirkin config = g_malloc(size); 427315a1350SMichael S. Tsirkin 428315a1350SMichael S. Tsirkin qemu_get_buffer(f, config, size); 429315a1350SMichael S. Tsirkin for (i = 0; i < size; ++i) { 430315a1350SMichael S. Tsirkin if ((config[i] ^ s->config[i]) & 431315a1350SMichael S. Tsirkin s->cmask[i] & ~s->wmask[i] & ~s->w1cmask[i]) { 4327c59364dSDr. David Alan Gilbert error_report("%s: Bad config data: i=0x%x read: %x device: %x " 4337c59364dSDr. David Alan Gilbert "cmask: %x wmask: %x w1cmask:%x", __func__, 4347c59364dSDr. David Alan Gilbert i, config[i], s->config[i], 4357c59364dSDr. David Alan Gilbert s->cmask[i], s->wmask[i], s->w1cmask[i]); 436315a1350SMichael S. Tsirkin g_free(config); 437315a1350SMichael S. Tsirkin return -EINVAL; 438315a1350SMichael S. Tsirkin } 439315a1350SMichael S. Tsirkin } 440315a1350SMichael S. Tsirkin memcpy(s->config, config, size); 441315a1350SMichael S. Tsirkin 442315a1350SMichael S. Tsirkin pci_update_mappings(s); 443e78e9ae4SDon Koch if (pc->is_bridge) { 444f055e96bSAndreas Färber PCIBridge *b = PCI_BRIDGE(s); 445e78e9ae4SDon Koch pci_bridge_update_mappings(b); 446e78e9ae4SDon Koch } 447315a1350SMichael S. Tsirkin 448315a1350SMichael S. Tsirkin memory_region_set_enabled(&s->bus_master_enable_region, 449315a1350SMichael S. Tsirkin pci_get_word(s->config + PCI_COMMAND) 450315a1350SMichael S. Tsirkin & PCI_COMMAND_MASTER); 451315a1350SMichael S. Tsirkin 452315a1350SMichael S. Tsirkin g_free(config); 453315a1350SMichael S. Tsirkin return 0; 454315a1350SMichael S. Tsirkin } 455315a1350SMichael S. Tsirkin 456315a1350SMichael S. Tsirkin /* just put buffer */ 457315a1350SMichael S. Tsirkin static void put_pci_config_device(QEMUFile *f, void *pv, size_t size) 458315a1350SMichael S. Tsirkin { 459315a1350SMichael S. Tsirkin const uint8_t **v = pv; 460315a1350SMichael S. Tsirkin assert(size == pci_config_size(container_of(pv, PCIDevice, config))); 461315a1350SMichael S. Tsirkin qemu_put_buffer(f, *v, size); 462315a1350SMichael S. Tsirkin } 463315a1350SMichael S. Tsirkin 464315a1350SMichael S. Tsirkin static VMStateInfo vmstate_info_pci_config = { 465315a1350SMichael S. Tsirkin .name = "pci config", 466315a1350SMichael S. Tsirkin .get = get_pci_config_device, 467315a1350SMichael S. Tsirkin .put = put_pci_config_device, 468315a1350SMichael S. Tsirkin }; 469315a1350SMichael S. Tsirkin 470315a1350SMichael S. Tsirkin static int get_pci_irq_state(QEMUFile *f, void *pv, size_t size) 471315a1350SMichael S. Tsirkin { 472315a1350SMichael S. Tsirkin PCIDevice *s = container_of(pv, PCIDevice, irq_state); 473315a1350SMichael S. Tsirkin uint32_t irq_state[PCI_NUM_PINS]; 474315a1350SMichael S. Tsirkin int i; 475315a1350SMichael S. Tsirkin for (i = 0; i < PCI_NUM_PINS; ++i) { 476315a1350SMichael S. Tsirkin irq_state[i] = qemu_get_be32(f); 477315a1350SMichael S. Tsirkin if (irq_state[i] != 0x1 && irq_state[i] != 0) { 478315a1350SMichael S. Tsirkin fprintf(stderr, "irq state %d: must be 0 or 1.\n", 479315a1350SMichael S. Tsirkin irq_state[i]); 480315a1350SMichael S. Tsirkin return -EINVAL; 481315a1350SMichael S. Tsirkin } 482315a1350SMichael S. Tsirkin } 483315a1350SMichael S. Tsirkin 484315a1350SMichael S. Tsirkin for (i = 0; i < PCI_NUM_PINS; ++i) { 485315a1350SMichael S. Tsirkin pci_set_irq_state(s, i, irq_state[i]); 486315a1350SMichael S. Tsirkin } 487315a1350SMichael S. Tsirkin 488315a1350SMichael S. Tsirkin return 0; 489315a1350SMichael S. Tsirkin } 490315a1350SMichael S. Tsirkin 491315a1350SMichael S. Tsirkin static void put_pci_irq_state(QEMUFile *f, void *pv, size_t size) 492315a1350SMichael S. Tsirkin { 493315a1350SMichael S. Tsirkin int i; 494315a1350SMichael S. Tsirkin PCIDevice *s = container_of(pv, PCIDevice, irq_state); 495315a1350SMichael S. Tsirkin 496315a1350SMichael S. Tsirkin for (i = 0; i < PCI_NUM_PINS; ++i) { 497315a1350SMichael S. Tsirkin qemu_put_be32(f, pci_irq_state(s, i)); 498315a1350SMichael S. Tsirkin } 499315a1350SMichael S. Tsirkin } 500315a1350SMichael S. Tsirkin 501315a1350SMichael S. Tsirkin static VMStateInfo vmstate_info_pci_irq_state = { 502315a1350SMichael S. Tsirkin .name = "pci irq state", 503315a1350SMichael S. Tsirkin .get = get_pci_irq_state, 504315a1350SMichael S. Tsirkin .put = put_pci_irq_state, 505315a1350SMichael S. Tsirkin }; 506315a1350SMichael S. Tsirkin 507315a1350SMichael S. Tsirkin const VMStateDescription vmstate_pci_device = { 508315a1350SMichael S. Tsirkin .name = "PCIDevice", 509315a1350SMichael S. Tsirkin .version_id = 2, 510315a1350SMichael S. Tsirkin .minimum_version_id = 1, 511315a1350SMichael S. Tsirkin .fields = (VMStateField[]) { 5123476436aSMichael S. Tsirkin VMSTATE_INT32_POSITIVE_LE(version_id, PCIDevice), 513315a1350SMichael S. Tsirkin VMSTATE_BUFFER_UNSAFE_INFO(config, PCIDevice, 0, 514315a1350SMichael S. Tsirkin vmstate_info_pci_config, 515315a1350SMichael S. Tsirkin PCI_CONFIG_SPACE_SIZE), 516315a1350SMichael S. Tsirkin VMSTATE_BUFFER_UNSAFE_INFO(irq_state, PCIDevice, 2, 517315a1350SMichael S. Tsirkin vmstate_info_pci_irq_state, 518315a1350SMichael S. Tsirkin PCI_NUM_PINS * sizeof(int32_t)), 519315a1350SMichael S. Tsirkin VMSTATE_END_OF_LIST() 520315a1350SMichael S. Tsirkin } 521315a1350SMichael S. Tsirkin }; 522315a1350SMichael S. Tsirkin 523315a1350SMichael S. Tsirkin const VMStateDescription vmstate_pcie_device = { 524315a1350SMichael S. Tsirkin .name = "PCIEDevice", 525315a1350SMichael S. Tsirkin .version_id = 2, 526315a1350SMichael S. Tsirkin .minimum_version_id = 1, 527315a1350SMichael S. Tsirkin .fields = (VMStateField[]) { 5283476436aSMichael S. Tsirkin VMSTATE_INT32_POSITIVE_LE(version_id, PCIDevice), 529315a1350SMichael S. Tsirkin VMSTATE_BUFFER_UNSAFE_INFO(config, PCIDevice, 0, 530315a1350SMichael S. Tsirkin vmstate_info_pci_config, 531315a1350SMichael S. Tsirkin PCIE_CONFIG_SPACE_SIZE), 532315a1350SMichael S. Tsirkin VMSTATE_BUFFER_UNSAFE_INFO(irq_state, PCIDevice, 2, 533315a1350SMichael S. Tsirkin vmstate_info_pci_irq_state, 534315a1350SMichael S. Tsirkin PCI_NUM_PINS * sizeof(int32_t)), 535315a1350SMichael S. Tsirkin VMSTATE_END_OF_LIST() 536315a1350SMichael S. Tsirkin } 537315a1350SMichael S. Tsirkin }; 538315a1350SMichael S. Tsirkin 539315a1350SMichael S. Tsirkin static inline const VMStateDescription *pci_get_vmstate(PCIDevice *s) 540315a1350SMichael S. Tsirkin { 541315a1350SMichael S. Tsirkin return pci_is_express(s) ? &vmstate_pcie_device : &vmstate_pci_device; 542315a1350SMichael S. Tsirkin } 543315a1350SMichael S. Tsirkin 544315a1350SMichael S. Tsirkin void pci_device_save(PCIDevice *s, QEMUFile *f) 545315a1350SMichael S. Tsirkin { 546315a1350SMichael S. Tsirkin /* Clear interrupt status bit: it is implicit 547315a1350SMichael S. Tsirkin * in irq_state which we are saving. 548315a1350SMichael S. Tsirkin * This makes us compatible with old devices 549315a1350SMichael S. Tsirkin * which never set or clear this bit. */ 550315a1350SMichael S. Tsirkin s->config[PCI_STATUS] &= ~PCI_STATUS_INTERRUPT; 5518118f095SAlexander Graf vmstate_save_state(f, pci_get_vmstate(s), s, NULL); 552315a1350SMichael S. Tsirkin /* Restore the interrupt status bit. */ 553315a1350SMichael S. Tsirkin pci_update_irq_status(s); 554315a1350SMichael S. Tsirkin } 555315a1350SMichael S. Tsirkin 556315a1350SMichael S. Tsirkin int pci_device_load(PCIDevice *s, QEMUFile *f) 557315a1350SMichael S. Tsirkin { 558315a1350SMichael S. Tsirkin int ret; 559315a1350SMichael S. Tsirkin ret = vmstate_load_state(f, pci_get_vmstate(s), s, s->version_id); 560315a1350SMichael S. Tsirkin /* Restore the interrupt status bit. */ 561315a1350SMichael S. Tsirkin pci_update_irq_status(s); 562315a1350SMichael S. Tsirkin return ret; 563315a1350SMichael S. Tsirkin } 564315a1350SMichael S. Tsirkin 565315a1350SMichael S. Tsirkin static void pci_set_default_subsystem_id(PCIDevice *pci_dev) 566315a1350SMichael S. Tsirkin { 567315a1350SMichael S. Tsirkin pci_set_word(pci_dev->config + PCI_SUBSYSTEM_VENDOR_ID, 568315a1350SMichael S. Tsirkin pci_default_sub_vendor_id); 569315a1350SMichael S. Tsirkin pci_set_word(pci_dev->config + PCI_SUBSYSTEM_ID, 570315a1350SMichael S. Tsirkin pci_default_sub_device_id); 571315a1350SMichael S. Tsirkin } 572315a1350SMichael S. Tsirkin 573315a1350SMichael S. Tsirkin /* 574315a1350SMichael S. Tsirkin * Parse [[<domain>:]<bus>:]<slot>, return -1 on error if funcp == NULL 575315a1350SMichael S. Tsirkin * [[<domain>:]<bus>:]<slot>.<func>, return -1 on error 576315a1350SMichael S. Tsirkin */ 5776dbcb819SMarkus Armbruster static int pci_parse_devaddr(const char *addr, int *domp, int *busp, 578315a1350SMichael S. Tsirkin unsigned int *slotp, unsigned int *funcp) 579315a1350SMichael S. Tsirkin { 580315a1350SMichael S. Tsirkin const char *p; 581315a1350SMichael S. Tsirkin char *e; 582315a1350SMichael S. Tsirkin unsigned long val; 583315a1350SMichael S. Tsirkin unsigned long dom = 0, bus = 0; 584315a1350SMichael S. Tsirkin unsigned int slot = 0; 585315a1350SMichael S. Tsirkin unsigned int func = 0; 586315a1350SMichael S. Tsirkin 587315a1350SMichael S. Tsirkin p = addr; 588315a1350SMichael S. Tsirkin val = strtoul(p, &e, 16); 589315a1350SMichael S. Tsirkin if (e == p) 590315a1350SMichael S. Tsirkin return -1; 591315a1350SMichael S. Tsirkin if (*e == ':') { 592315a1350SMichael S. Tsirkin bus = val; 593315a1350SMichael S. Tsirkin p = e + 1; 594315a1350SMichael S. Tsirkin val = strtoul(p, &e, 16); 595315a1350SMichael S. Tsirkin if (e == p) 596315a1350SMichael S. Tsirkin return -1; 597315a1350SMichael S. Tsirkin if (*e == ':') { 598315a1350SMichael S. Tsirkin dom = bus; 599315a1350SMichael S. Tsirkin bus = val; 600315a1350SMichael S. Tsirkin p = e + 1; 601315a1350SMichael S. Tsirkin val = strtoul(p, &e, 16); 602315a1350SMichael S. Tsirkin if (e == p) 603315a1350SMichael S. Tsirkin return -1; 604315a1350SMichael S. Tsirkin } 605315a1350SMichael S. Tsirkin } 606315a1350SMichael S. Tsirkin 607315a1350SMichael S. Tsirkin slot = val; 608315a1350SMichael S. Tsirkin 609315a1350SMichael S. Tsirkin if (funcp != NULL) { 610315a1350SMichael S. Tsirkin if (*e != '.') 611315a1350SMichael S. Tsirkin return -1; 612315a1350SMichael S. Tsirkin 613315a1350SMichael S. Tsirkin p = e + 1; 614315a1350SMichael S. Tsirkin val = strtoul(p, &e, 16); 615315a1350SMichael S. Tsirkin if (e == p) 616315a1350SMichael S. Tsirkin return -1; 617315a1350SMichael S. Tsirkin 618315a1350SMichael S. Tsirkin func = val; 619315a1350SMichael S. Tsirkin } 620315a1350SMichael S. Tsirkin 621315a1350SMichael S. Tsirkin /* if funcp == NULL func is 0 */ 622315a1350SMichael S. Tsirkin if (dom > 0xffff || bus > 0xff || slot > 0x1f || func > 7) 623315a1350SMichael S. Tsirkin return -1; 624315a1350SMichael S. Tsirkin 625315a1350SMichael S. Tsirkin if (*e) 626315a1350SMichael S. Tsirkin return -1; 627315a1350SMichael S. Tsirkin 628315a1350SMichael S. Tsirkin *domp = dom; 629315a1350SMichael S. Tsirkin *busp = bus; 630315a1350SMichael S. Tsirkin *slotp = slot; 631315a1350SMichael S. Tsirkin if (funcp != NULL) 632315a1350SMichael S. Tsirkin *funcp = func; 633315a1350SMichael S. Tsirkin return 0; 634315a1350SMichael S. Tsirkin } 635315a1350SMichael S. Tsirkin 6366dbcb819SMarkus Armbruster static PCIBus *pci_get_bus_devfn(int *devfnp, PCIBus *root, 6376dbcb819SMarkus Armbruster const char *devaddr) 638315a1350SMichael S. Tsirkin { 639315a1350SMichael S. Tsirkin int dom, bus; 640315a1350SMichael S. Tsirkin unsigned slot; 641315a1350SMichael S. Tsirkin 6421ef7a2a2SDavid Gibson if (!root) { 6431ef7a2a2SDavid Gibson fprintf(stderr, "No primary PCI bus\n"); 6441ef7a2a2SDavid Gibson return NULL; 6451ef7a2a2SDavid Gibson } 6461ef7a2a2SDavid Gibson 647b645000eSSaravanakumar assert(!root->parent_dev); 648b645000eSSaravanakumar 649315a1350SMichael S. Tsirkin if (!devaddr) { 650315a1350SMichael S. Tsirkin *devfnp = -1; 6511ef7a2a2SDavid Gibson return pci_find_bus_nr(root, 0); 652315a1350SMichael S. Tsirkin } 653315a1350SMichael S. Tsirkin 654315a1350SMichael S. Tsirkin if (pci_parse_devaddr(devaddr, &dom, &bus, &slot, NULL) < 0) { 655315a1350SMichael S. Tsirkin return NULL; 656315a1350SMichael S. Tsirkin } 657315a1350SMichael S. Tsirkin 6581ef7a2a2SDavid Gibson if (dom != 0) { 6591ef7a2a2SDavid Gibson fprintf(stderr, "No support for non-zero PCI domains\n"); 6601ef7a2a2SDavid Gibson return NULL; 6611ef7a2a2SDavid Gibson } 6621ef7a2a2SDavid Gibson 663315a1350SMichael S. Tsirkin *devfnp = PCI_DEVFN(slot, 0); 6641ef7a2a2SDavid Gibson return pci_find_bus_nr(root, bus); 665315a1350SMichael S. Tsirkin } 666315a1350SMichael S. Tsirkin 667315a1350SMichael S. Tsirkin static void pci_init_cmask(PCIDevice *dev) 668315a1350SMichael S. Tsirkin { 669315a1350SMichael S. Tsirkin pci_set_word(dev->cmask + PCI_VENDOR_ID, 0xffff); 670315a1350SMichael S. Tsirkin pci_set_word(dev->cmask + PCI_DEVICE_ID, 0xffff); 671315a1350SMichael S. Tsirkin dev->cmask[PCI_STATUS] = PCI_STATUS_CAP_LIST; 672315a1350SMichael S. Tsirkin dev->cmask[PCI_REVISION_ID] = 0xff; 673315a1350SMichael S. Tsirkin dev->cmask[PCI_CLASS_PROG] = 0xff; 674315a1350SMichael S. Tsirkin pci_set_word(dev->cmask + PCI_CLASS_DEVICE, 0xffff); 675315a1350SMichael S. Tsirkin dev->cmask[PCI_HEADER_TYPE] = 0xff; 676315a1350SMichael S. Tsirkin dev->cmask[PCI_CAPABILITY_LIST] = 0xff; 677315a1350SMichael S. Tsirkin } 678315a1350SMichael S. Tsirkin 679315a1350SMichael S. Tsirkin static void pci_init_wmask(PCIDevice *dev) 680315a1350SMichael S. Tsirkin { 681315a1350SMichael S. Tsirkin int config_size = pci_config_size(dev); 682315a1350SMichael S. Tsirkin 683315a1350SMichael S. Tsirkin dev->wmask[PCI_CACHE_LINE_SIZE] = 0xff; 684315a1350SMichael S. Tsirkin dev->wmask[PCI_INTERRUPT_LINE] = 0xff; 685315a1350SMichael S. Tsirkin pci_set_word(dev->wmask + PCI_COMMAND, 686315a1350SMichael S. Tsirkin PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | 687315a1350SMichael S. Tsirkin PCI_COMMAND_INTX_DISABLE); 688315a1350SMichael S. Tsirkin if (dev->cap_present & QEMU_PCI_CAP_SERR) { 689315a1350SMichael S. Tsirkin pci_word_test_and_set_mask(dev->wmask + PCI_COMMAND, PCI_COMMAND_SERR); 690315a1350SMichael S. Tsirkin } 691315a1350SMichael S. Tsirkin 692315a1350SMichael S. Tsirkin memset(dev->wmask + PCI_CONFIG_HEADER_SIZE, 0xff, 693315a1350SMichael S. Tsirkin config_size - PCI_CONFIG_HEADER_SIZE); 694315a1350SMichael S. Tsirkin } 695315a1350SMichael S. Tsirkin 696315a1350SMichael S. Tsirkin static void pci_init_w1cmask(PCIDevice *dev) 697315a1350SMichael S. Tsirkin { 698315a1350SMichael S. Tsirkin /* 699315a1350SMichael S. Tsirkin * Note: It's okay to set w1cmask even for readonly bits as 700315a1350SMichael S. Tsirkin * long as their value is hardwired to 0. 701315a1350SMichael S. Tsirkin */ 702315a1350SMichael S. Tsirkin pci_set_word(dev->w1cmask + PCI_STATUS, 703315a1350SMichael S. Tsirkin PCI_STATUS_PARITY | PCI_STATUS_SIG_TARGET_ABORT | 704315a1350SMichael S. Tsirkin PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_REC_MASTER_ABORT | 705315a1350SMichael S. Tsirkin PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY); 706315a1350SMichael S. Tsirkin } 707315a1350SMichael S. Tsirkin 708315a1350SMichael S. Tsirkin static void pci_init_mask_bridge(PCIDevice *d) 709315a1350SMichael S. Tsirkin { 710315a1350SMichael S. Tsirkin /* PCI_PRIMARY_BUS, PCI_SECONDARY_BUS, PCI_SUBORDINATE_BUS and 711315a1350SMichael S. Tsirkin PCI_SEC_LETENCY_TIMER */ 712315a1350SMichael S. Tsirkin memset(d->wmask + PCI_PRIMARY_BUS, 0xff, 4); 713315a1350SMichael S. Tsirkin 714315a1350SMichael S. Tsirkin /* base and limit */ 715315a1350SMichael S. Tsirkin d->wmask[PCI_IO_BASE] = PCI_IO_RANGE_MASK & 0xff; 716315a1350SMichael S. Tsirkin d->wmask[PCI_IO_LIMIT] = PCI_IO_RANGE_MASK & 0xff; 717315a1350SMichael S. Tsirkin pci_set_word(d->wmask + PCI_MEMORY_BASE, 718315a1350SMichael S. Tsirkin PCI_MEMORY_RANGE_MASK & 0xffff); 719315a1350SMichael S. Tsirkin pci_set_word(d->wmask + PCI_MEMORY_LIMIT, 720315a1350SMichael S. Tsirkin PCI_MEMORY_RANGE_MASK & 0xffff); 721315a1350SMichael S. Tsirkin pci_set_word(d->wmask + PCI_PREF_MEMORY_BASE, 722315a1350SMichael S. Tsirkin PCI_PREF_RANGE_MASK & 0xffff); 723315a1350SMichael S. Tsirkin pci_set_word(d->wmask + PCI_PREF_MEMORY_LIMIT, 724315a1350SMichael S. Tsirkin PCI_PREF_RANGE_MASK & 0xffff); 725315a1350SMichael S. Tsirkin 726315a1350SMichael S. Tsirkin /* PCI_PREF_BASE_UPPER32 and PCI_PREF_LIMIT_UPPER32 */ 727315a1350SMichael S. Tsirkin memset(d->wmask + PCI_PREF_BASE_UPPER32, 0xff, 8); 728315a1350SMichael S. Tsirkin 729315a1350SMichael S. Tsirkin /* Supported memory and i/o types */ 730315a1350SMichael S. Tsirkin d->config[PCI_IO_BASE] |= PCI_IO_RANGE_TYPE_16; 731315a1350SMichael S. Tsirkin d->config[PCI_IO_LIMIT] |= PCI_IO_RANGE_TYPE_16; 732315a1350SMichael S. Tsirkin pci_word_test_and_set_mask(d->config + PCI_PREF_MEMORY_BASE, 733315a1350SMichael S. Tsirkin PCI_PREF_RANGE_TYPE_64); 734315a1350SMichael S. Tsirkin pci_word_test_and_set_mask(d->config + PCI_PREF_MEMORY_LIMIT, 735315a1350SMichael S. Tsirkin PCI_PREF_RANGE_TYPE_64); 736315a1350SMichael S. Tsirkin 737ba7d8515SAlex Williamson /* 738ba7d8515SAlex Williamson * TODO: Bridges default to 10-bit VGA decoding but we currently only 739ba7d8515SAlex Williamson * implement 16-bit decoding (no alias support). 740ba7d8515SAlex Williamson */ 741315a1350SMichael S. Tsirkin pci_set_word(d->wmask + PCI_BRIDGE_CONTROL, 742315a1350SMichael S. Tsirkin PCI_BRIDGE_CTL_PARITY | 743315a1350SMichael S. Tsirkin PCI_BRIDGE_CTL_SERR | 744315a1350SMichael S. Tsirkin PCI_BRIDGE_CTL_ISA | 745315a1350SMichael S. Tsirkin PCI_BRIDGE_CTL_VGA | 746315a1350SMichael S. Tsirkin PCI_BRIDGE_CTL_VGA_16BIT | 747315a1350SMichael S. Tsirkin PCI_BRIDGE_CTL_MASTER_ABORT | 748315a1350SMichael S. Tsirkin PCI_BRIDGE_CTL_BUS_RESET | 749315a1350SMichael S. Tsirkin PCI_BRIDGE_CTL_FAST_BACK | 750315a1350SMichael S. Tsirkin PCI_BRIDGE_CTL_DISCARD | 751315a1350SMichael S. Tsirkin PCI_BRIDGE_CTL_SEC_DISCARD | 752315a1350SMichael S. Tsirkin PCI_BRIDGE_CTL_DISCARD_SERR); 753315a1350SMichael S. Tsirkin /* Below does not do anything as we never set this bit, put here for 754315a1350SMichael S. Tsirkin * completeness. */ 755315a1350SMichael S. Tsirkin pci_set_word(d->w1cmask + PCI_BRIDGE_CONTROL, 756315a1350SMichael S. Tsirkin PCI_BRIDGE_CTL_DISCARD_STATUS); 757315a1350SMichael S. Tsirkin d->cmask[PCI_IO_BASE] |= PCI_IO_RANGE_TYPE_MASK; 758315a1350SMichael S. Tsirkin d->cmask[PCI_IO_LIMIT] |= PCI_IO_RANGE_TYPE_MASK; 759315a1350SMichael S. Tsirkin pci_word_test_and_set_mask(d->cmask + PCI_PREF_MEMORY_BASE, 760315a1350SMichael S. Tsirkin PCI_PREF_RANGE_TYPE_MASK); 761315a1350SMichael S. Tsirkin pci_word_test_and_set_mask(d->cmask + PCI_PREF_MEMORY_LIMIT, 762315a1350SMichael S. Tsirkin PCI_PREF_RANGE_TYPE_MASK); 763315a1350SMichael S. Tsirkin } 764315a1350SMichael S. Tsirkin 765133e9b22SMarkus Armbruster static void pci_init_multifunction(PCIBus *bus, PCIDevice *dev, Error **errp) 766315a1350SMichael S. Tsirkin { 767315a1350SMichael S. Tsirkin uint8_t slot = PCI_SLOT(dev->devfn); 768315a1350SMichael S. Tsirkin uint8_t func; 769315a1350SMichael S. Tsirkin 770315a1350SMichael S. Tsirkin if (dev->cap_present & QEMU_PCI_CAP_MULTIFUNCTION) { 771315a1350SMichael S. Tsirkin dev->config[PCI_HEADER_TYPE] |= PCI_HEADER_TYPE_MULTI_FUNCTION; 772315a1350SMichael S. Tsirkin } 773315a1350SMichael S. Tsirkin 774315a1350SMichael S. Tsirkin /* 775315a1350SMichael S. Tsirkin * multifunction bit is interpreted in two ways as follows. 776315a1350SMichael S. Tsirkin * - all functions must set the bit to 1. 777315a1350SMichael S. Tsirkin * Example: Intel X53 778315a1350SMichael S. Tsirkin * - function 0 must set the bit, but the rest function (> 0) 779315a1350SMichael S. Tsirkin * is allowed to leave the bit to 0. 780315a1350SMichael S. Tsirkin * Example: PIIX3(also in qemu), PIIX4(also in qemu), ICH10, 781315a1350SMichael S. Tsirkin * 782315a1350SMichael S. Tsirkin * So OS (at least Linux) checks the bit of only function 0, 783315a1350SMichael S. Tsirkin * and doesn't see the bit of function > 0. 784315a1350SMichael S. Tsirkin * 785315a1350SMichael S. Tsirkin * The below check allows both interpretation. 786315a1350SMichael S. Tsirkin */ 787315a1350SMichael S. Tsirkin if (PCI_FUNC(dev->devfn)) { 788315a1350SMichael S. Tsirkin PCIDevice *f0 = bus->devices[PCI_DEVFN(slot, 0)]; 789315a1350SMichael S. Tsirkin if (f0 && !(f0->cap_present & QEMU_PCI_CAP_MULTIFUNCTION)) { 790315a1350SMichael S. Tsirkin /* function 0 should set multifunction bit */ 791133e9b22SMarkus Armbruster error_setg(errp, "PCI: single function device can't be populated " 792315a1350SMichael S. Tsirkin "in function %x.%x", slot, PCI_FUNC(dev->devfn)); 793133e9b22SMarkus Armbruster return; 794315a1350SMichael S. Tsirkin } 795133e9b22SMarkus Armbruster return; 796315a1350SMichael S. Tsirkin } 797315a1350SMichael S. Tsirkin 798315a1350SMichael S. Tsirkin if (dev->cap_present & QEMU_PCI_CAP_MULTIFUNCTION) { 799133e9b22SMarkus Armbruster return; 800315a1350SMichael S. Tsirkin } 801315a1350SMichael S. Tsirkin /* function 0 indicates single function, so function > 0 must be NULL */ 802315a1350SMichael S. Tsirkin for (func = 1; func < PCI_FUNC_MAX; ++func) { 803315a1350SMichael S. Tsirkin if (bus->devices[PCI_DEVFN(slot, func)]) { 804133e9b22SMarkus Armbruster error_setg(errp, "PCI: %x.0 indicates single function, " 805315a1350SMichael S. Tsirkin "but %x.%x is already populated.", 806315a1350SMichael S. Tsirkin slot, slot, func); 807133e9b22SMarkus Armbruster return; 808315a1350SMichael S. Tsirkin } 809315a1350SMichael S. Tsirkin } 810315a1350SMichael S. Tsirkin } 811315a1350SMichael S. Tsirkin 812315a1350SMichael S. Tsirkin static void pci_config_alloc(PCIDevice *pci_dev) 813315a1350SMichael S. Tsirkin { 814315a1350SMichael S. Tsirkin int config_size = pci_config_size(pci_dev); 815315a1350SMichael S. Tsirkin 816315a1350SMichael S. Tsirkin pci_dev->config = g_malloc0(config_size); 817315a1350SMichael S. Tsirkin pci_dev->cmask = g_malloc0(config_size); 818315a1350SMichael S. Tsirkin pci_dev->wmask = g_malloc0(config_size); 819315a1350SMichael S. Tsirkin pci_dev->w1cmask = g_malloc0(config_size); 820315a1350SMichael S. Tsirkin pci_dev->used = g_malloc0(config_size); 821315a1350SMichael S. Tsirkin } 822315a1350SMichael S. Tsirkin 823315a1350SMichael S. Tsirkin static void pci_config_free(PCIDevice *pci_dev) 824315a1350SMichael S. Tsirkin { 825315a1350SMichael S. Tsirkin g_free(pci_dev->config); 826315a1350SMichael S. Tsirkin g_free(pci_dev->cmask); 827315a1350SMichael S. Tsirkin g_free(pci_dev->wmask); 828315a1350SMichael S. Tsirkin g_free(pci_dev->w1cmask); 829315a1350SMichael S. Tsirkin g_free(pci_dev->used); 830315a1350SMichael S. Tsirkin } 831315a1350SMichael S. Tsirkin 83230607764SMarcel Apfelbaum static void do_pci_unregister_device(PCIDevice *pci_dev) 83330607764SMarcel Apfelbaum { 83430607764SMarcel Apfelbaum pci_dev->bus->devices[pci_dev->devfn] = NULL; 83530607764SMarcel Apfelbaum pci_config_free(pci_dev); 83630607764SMarcel Apfelbaum 83730607764SMarcel Apfelbaum address_space_destroy(&pci_dev->bus_master_as); 83830607764SMarcel Apfelbaum } 83930607764SMarcel Apfelbaum 840315a1350SMichael S. Tsirkin /* -1 for devfn means auto assign */ 841315a1350SMichael S. Tsirkin static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus, 842133e9b22SMarkus Armbruster const char *name, int devfn, 843133e9b22SMarkus Armbruster Error **errp) 844315a1350SMichael S. Tsirkin { 845315a1350SMichael S. Tsirkin PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev); 846315a1350SMichael S. Tsirkin PCIConfigReadFunc *config_read = pc->config_read; 847315a1350SMichael S. Tsirkin PCIConfigWriteFunc *config_write = pc->config_write; 848133e9b22SMarkus Armbruster Error *local_err = NULL; 849e00387d5SAvi Kivity AddressSpace *dma_as; 850315a1350SMichael S. Tsirkin 851315a1350SMichael S. Tsirkin if (devfn < 0) { 852315a1350SMichael S. Tsirkin for(devfn = bus->devfn_min ; devfn < ARRAY_SIZE(bus->devices); 853315a1350SMichael S. Tsirkin devfn += PCI_FUNC_MAX) { 854315a1350SMichael S. Tsirkin if (!bus->devices[devfn]) 855315a1350SMichael S. Tsirkin goto found; 856315a1350SMichael S. Tsirkin } 857133e9b22SMarkus Armbruster error_setg(errp, "PCI: no slot/function available for %s, all in use", 858133e9b22SMarkus Armbruster name); 859315a1350SMichael S. Tsirkin return NULL; 860315a1350SMichael S. Tsirkin found: ; 861315a1350SMichael S. Tsirkin } else if (bus->devices[devfn]) { 862133e9b22SMarkus Armbruster error_setg(errp, "PCI: slot %d function %d not available for %s," 863133e9b22SMarkus Armbruster " in use by %s", 864133e9b22SMarkus Armbruster PCI_SLOT(devfn), PCI_FUNC(devfn), name, 865133e9b22SMarkus Armbruster bus->devices[devfn]->name); 866315a1350SMichael S. Tsirkin return NULL; 867315a1350SMichael S. Tsirkin } 868e00387d5SAvi Kivity 869315a1350SMichael S. Tsirkin pci_dev->bus = bus; 870efc8188eSLe Tan pci_dev->devfn = devfn; 8719eda7d37SAlexey Kardashevskiy dma_as = pci_device_iommu_address_space(pci_dev); 872e00387d5SAvi Kivity 87340c5dce9SPaolo Bonzini memory_region_init_alias(&pci_dev->bus_master_enable_region, 87440c5dce9SPaolo Bonzini OBJECT(pci_dev), "bus master", 875e00387d5SAvi Kivity dma_as->root, 0, memory_region_size(dma_as->root)); 876315a1350SMichael S. Tsirkin memory_region_set_enabled(&pci_dev->bus_master_enable_region, false); 8777dca8043SAlexey Kardashevskiy address_space_init(&pci_dev->bus_master_as, &pci_dev->bus_master_enable_region, 8787dca8043SAlexey Kardashevskiy name); 87924addbc7SPaolo Bonzini 880315a1350SMichael S. Tsirkin pstrcpy(pci_dev->name, sizeof(pci_dev->name), name); 881315a1350SMichael S. Tsirkin pci_dev->irq_state = 0; 882315a1350SMichael S. Tsirkin pci_config_alloc(pci_dev); 883315a1350SMichael S. Tsirkin 884315a1350SMichael S. Tsirkin pci_config_set_vendor_id(pci_dev->config, pc->vendor_id); 885315a1350SMichael S. Tsirkin pci_config_set_device_id(pci_dev->config, pc->device_id); 886315a1350SMichael S. Tsirkin pci_config_set_revision(pci_dev->config, pc->revision); 887315a1350SMichael S. Tsirkin pci_config_set_class(pci_dev->config, pc->class_id); 888315a1350SMichael S. Tsirkin 889315a1350SMichael S. Tsirkin if (!pc->is_bridge) { 890315a1350SMichael S. Tsirkin if (pc->subsystem_vendor_id || pc->subsystem_id) { 891315a1350SMichael S. Tsirkin pci_set_word(pci_dev->config + PCI_SUBSYSTEM_VENDOR_ID, 892315a1350SMichael S. Tsirkin pc->subsystem_vendor_id); 893315a1350SMichael S. Tsirkin pci_set_word(pci_dev->config + PCI_SUBSYSTEM_ID, 894315a1350SMichael S. Tsirkin pc->subsystem_id); 895315a1350SMichael S. Tsirkin } else { 896315a1350SMichael S. Tsirkin pci_set_default_subsystem_id(pci_dev); 897315a1350SMichael S. Tsirkin } 898315a1350SMichael S. Tsirkin } else { 899315a1350SMichael S. Tsirkin /* subsystem_vendor_id/subsystem_id are only for header type 0 */ 900315a1350SMichael S. Tsirkin assert(!pc->subsystem_vendor_id); 901315a1350SMichael S. Tsirkin assert(!pc->subsystem_id); 902315a1350SMichael S. Tsirkin } 903315a1350SMichael S. Tsirkin pci_init_cmask(pci_dev); 904315a1350SMichael S. Tsirkin pci_init_wmask(pci_dev); 905315a1350SMichael S. Tsirkin pci_init_w1cmask(pci_dev); 906315a1350SMichael S. Tsirkin if (pc->is_bridge) { 907315a1350SMichael S. Tsirkin pci_init_mask_bridge(pci_dev); 908315a1350SMichael S. Tsirkin } 909133e9b22SMarkus Armbruster pci_init_multifunction(bus, pci_dev, &local_err); 910133e9b22SMarkus Armbruster if (local_err) { 911133e9b22SMarkus Armbruster error_propagate(errp, local_err); 91230607764SMarcel Apfelbaum do_pci_unregister_device(pci_dev); 913315a1350SMichael S. Tsirkin return NULL; 914315a1350SMichael S. Tsirkin } 915315a1350SMichael S. Tsirkin 916315a1350SMichael S. Tsirkin if (!config_read) 917315a1350SMichael S. Tsirkin config_read = pci_default_read_config; 918315a1350SMichael S. Tsirkin if (!config_write) 919315a1350SMichael S. Tsirkin config_write = pci_default_write_config; 920315a1350SMichael S. Tsirkin pci_dev->config_read = config_read; 921315a1350SMichael S. Tsirkin pci_dev->config_write = config_write; 922315a1350SMichael S. Tsirkin bus->devices[devfn] = pci_dev; 923315a1350SMichael S. Tsirkin pci_dev->version_id = 2; /* Current pci device vmstate version */ 924315a1350SMichael S. Tsirkin return pci_dev; 925315a1350SMichael S. Tsirkin } 926315a1350SMichael S. Tsirkin 927315a1350SMichael S. Tsirkin static void pci_unregister_io_regions(PCIDevice *pci_dev) 928315a1350SMichael S. Tsirkin { 929315a1350SMichael S. Tsirkin PCIIORegion *r; 930315a1350SMichael S. Tsirkin int i; 931315a1350SMichael S. Tsirkin 932315a1350SMichael S. Tsirkin for(i = 0; i < PCI_NUM_REGIONS; i++) { 933315a1350SMichael S. Tsirkin r = &pci_dev->io_regions[i]; 934315a1350SMichael S. Tsirkin if (!r->size || r->addr == PCI_BAR_UNMAPPED) 935315a1350SMichael S. Tsirkin continue; 936315a1350SMichael S. Tsirkin memory_region_del_subregion(r->address_space, r->memory); 937315a1350SMichael S. Tsirkin } 938e01fd687SAlex Williamson 939e01fd687SAlex Williamson pci_unregister_vga(pci_dev); 940315a1350SMichael S. Tsirkin } 941315a1350SMichael S. Tsirkin 942133e9b22SMarkus Armbruster static void pci_qdev_unrealize(DeviceState *dev, Error **errp) 943315a1350SMichael S. Tsirkin { 944315a1350SMichael S. Tsirkin PCIDevice *pci_dev = PCI_DEVICE(dev); 945315a1350SMichael S. Tsirkin PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev); 946315a1350SMichael S. Tsirkin 947315a1350SMichael S. Tsirkin pci_unregister_io_regions(pci_dev); 948315a1350SMichael S. Tsirkin pci_del_option_rom(pci_dev); 949315a1350SMichael S. Tsirkin 950315a1350SMichael S. Tsirkin if (pc->exit) { 951315a1350SMichael S. Tsirkin pc->exit(pci_dev); 952315a1350SMichael S. Tsirkin } 953315a1350SMichael S. Tsirkin 954315a1350SMichael S. Tsirkin do_pci_unregister_device(pci_dev); 955315a1350SMichael S. Tsirkin } 956315a1350SMichael S. Tsirkin 957315a1350SMichael S. Tsirkin void pci_register_bar(PCIDevice *pci_dev, int region_num, 958315a1350SMichael S. Tsirkin uint8_t type, MemoryRegion *memory) 959315a1350SMichael S. Tsirkin { 960315a1350SMichael S. Tsirkin PCIIORegion *r; 961315a1350SMichael S. Tsirkin uint32_t addr; 962315a1350SMichael S. Tsirkin uint64_t wmask; 963315a1350SMichael S. Tsirkin pcibus_t size = memory_region_size(memory); 964315a1350SMichael S. Tsirkin 965315a1350SMichael S. Tsirkin assert(region_num >= 0); 966315a1350SMichael S. Tsirkin assert(region_num < PCI_NUM_REGIONS); 967315a1350SMichael S. Tsirkin if (size & (size-1)) { 968315a1350SMichael S. Tsirkin fprintf(stderr, "ERROR: PCI region size must be pow2 " 969315a1350SMichael S. Tsirkin "type=0x%x, size=0x%"FMT_PCIBUS"\n", type, size); 970315a1350SMichael S. Tsirkin exit(1); 971315a1350SMichael S. Tsirkin } 972315a1350SMichael S. Tsirkin 973315a1350SMichael S. Tsirkin r = &pci_dev->io_regions[region_num]; 974315a1350SMichael S. Tsirkin r->addr = PCI_BAR_UNMAPPED; 975315a1350SMichael S. Tsirkin r->size = size; 976315a1350SMichael S. Tsirkin r->type = type; 977315a1350SMichael S. Tsirkin r->memory = NULL; 978315a1350SMichael S. Tsirkin 979315a1350SMichael S. Tsirkin wmask = ~(size - 1); 980315a1350SMichael S. Tsirkin addr = pci_bar(pci_dev, region_num); 981315a1350SMichael S. Tsirkin if (region_num == PCI_ROM_SLOT) { 982315a1350SMichael S. Tsirkin /* ROM enable bit is writable */ 983315a1350SMichael S. Tsirkin wmask |= PCI_ROM_ADDRESS_ENABLE; 984315a1350SMichael S. Tsirkin } 985315a1350SMichael S. Tsirkin pci_set_long(pci_dev->config + addr, type); 986315a1350SMichael S. Tsirkin if (!(r->type & PCI_BASE_ADDRESS_SPACE_IO) && 987315a1350SMichael S. Tsirkin r->type & PCI_BASE_ADDRESS_MEM_TYPE_64) { 988315a1350SMichael S. Tsirkin pci_set_quad(pci_dev->wmask + addr, wmask); 989315a1350SMichael S. Tsirkin pci_set_quad(pci_dev->cmask + addr, ~0ULL); 990315a1350SMichael S. Tsirkin } else { 991315a1350SMichael S. Tsirkin pci_set_long(pci_dev->wmask + addr, wmask & 0xffffffff); 992315a1350SMichael S. Tsirkin pci_set_long(pci_dev->cmask + addr, 0xffffffff); 993315a1350SMichael S. Tsirkin } 994315a1350SMichael S. Tsirkin pci_dev->io_regions[region_num].memory = memory; 995315a1350SMichael S. Tsirkin pci_dev->io_regions[region_num].address_space 996315a1350SMichael S. Tsirkin = type & PCI_BASE_ADDRESS_SPACE_IO 997315a1350SMichael S. Tsirkin ? pci_dev->bus->address_space_io 998315a1350SMichael S. Tsirkin : pci_dev->bus->address_space_mem; 999315a1350SMichael S. Tsirkin } 1000315a1350SMichael S. Tsirkin 1001e01fd687SAlex Williamson static void pci_update_vga(PCIDevice *pci_dev) 1002e01fd687SAlex Williamson { 1003e01fd687SAlex Williamson uint16_t cmd; 1004e01fd687SAlex Williamson 1005e01fd687SAlex Williamson if (!pci_dev->has_vga) { 1006e01fd687SAlex Williamson return; 1007e01fd687SAlex Williamson } 1008e01fd687SAlex Williamson 1009e01fd687SAlex Williamson cmd = pci_get_word(pci_dev->config + PCI_COMMAND); 1010e01fd687SAlex Williamson 1011e01fd687SAlex Williamson memory_region_set_enabled(pci_dev->vga_regions[QEMU_PCI_VGA_MEM], 1012e01fd687SAlex Williamson cmd & PCI_COMMAND_MEMORY); 1013e01fd687SAlex Williamson memory_region_set_enabled(pci_dev->vga_regions[QEMU_PCI_VGA_IO_LO], 1014e01fd687SAlex Williamson cmd & PCI_COMMAND_IO); 1015e01fd687SAlex Williamson memory_region_set_enabled(pci_dev->vga_regions[QEMU_PCI_VGA_IO_HI], 1016e01fd687SAlex Williamson cmd & PCI_COMMAND_IO); 1017e01fd687SAlex Williamson } 1018e01fd687SAlex Williamson 1019e01fd687SAlex Williamson void pci_register_vga(PCIDevice *pci_dev, MemoryRegion *mem, 1020e01fd687SAlex Williamson MemoryRegion *io_lo, MemoryRegion *io_hi) 1021e01fd687SAlex Williamson { 1022e01fd687SAlex Williamson assert(!pci_dev->has_vga); 1023e01fd687SAlex Williamson 1024e01fd687SAlex Williamson assert(memory_region_size(mem) == QEMU_PCI_VGA_MEM_SIZE); 1025e01fd687SAlex Williamson pci_dev->vga_regions[QEMU_PCI_VGA_MEM] = mem; 1026e01fd687SAlex Williamson memory_region_add_subregion_overlap(pci_dev->bus->address_space_mem, 1027e01fd687SAlex Williamson QEMU_PCI_VGA_MEM_BASE, mem, 1); 1028e01fd687SAlex Williamson 1029e01fd687SAlex Williamson assert(memory_region_size(io_lo) == QEMU_PCI_VGA_IO_LO_SIZE); 1030e01fd687SAlex Williamson pci_dev->vga_regions[QEMU_PCI_VGA_IO_LO] = io_lo; 1031e01fd687SAlex Williamson memory_region_add_subregion_overlap(pci_dev->bus->address_space_io, 1032e01fd687SAlex Williamson QEMU_PCI_VGA_IO_LO_BASE, io_lo, 1); 1033e01fd687SAlex Williamson 1034e01fd687SAlex Williamson assert(memory_region_size(io_hi) == QEMU_PCI_VGA_IO_HI_SIZE); 1035e01fd687SAlex Williamson pci_dev->vga_regions[QEMU_PCI_VGA_IO_HI] = io_hi; 1036e01fd687SAlex Williamson memory_region_add_subregion_overlap(pci_dev->bus->address_space_io, 1037e01fd687SAlex Williamson QEMU_PCI_VGA_IO_HI_BASE, io_hi, 1); 1038e01fd687SAlex Williamson pci_dev->has_vga = true; 1039e01fd687SAlex Williamson 1040e01fd687SAlex Williamson pci_update_vga(pci_dev); 1041e01fd687SAlex Williamson } 1042e01fd687SAlex Williamson 1043e01fd687SAlex Williamson void pci_unregister_vga(PCIDevice *pci_dev) 1044e01fd687SAlex Williamson { 1045e01fd687SAlex Williamson if (!pci_dev->has_vga) { 1046e01fd687SAlex Williamson return; 1047e01fd687SAlex Williamson } 1048e01fd687SAlex Williamson 1049e01fd687SAlex Williamson memory_region_del_subregion(pci_dev->bus->address_space_mem, 1050e01fd687SAlex Williamson pci_dev->vga_regions[QEMU_PCI_VGA_MEM]); 1051e01fd687SAlex Williamson memory_region_del_subregion(pci_dev->bus->address_space_io, 1052e01fd687SAlex Williamson pci_dev->vga_regions[QEMU_PCI_VGA_IO_LO]); 1053e01fd687SAlex Williamson memory_region_del_subregion(pci_dev->bus->address_space_io, 1054e01fd687SAlex Williamson pci_dev->vga_regions[QEMU_PCI_VGA_IO_HI]); 1055e01fd687SAlex Williamson pci_dev->has_vga = false; 1056e01fd687SAlex Williamson } 1057e01fd687SAlex Williamson 1058315a1350SMichael S. Tsirkin pcibus_t pci_get_bar_addr(PCIDevice *pci_dev, int region_num) 1059315a1350SMichael S. Tsirkin { 1060315a1350SMichael S. Tsirkin return pci_dev->io_regions[region_num].addr; 1061315a1350SMichael S. Tsirkin } 1062315a1350SMichael S. Tsirkin 1063315a1350SMichael S. Tsirkin static pcibus_t pci_bar_address(PCIDevice *d, 1064315a1350SMichael S. Tsirkin int reg, uint8_t type, pcibus_t size) 1065315a1350SMichael S. Tsirkin { 1066315a1350SMichael S. Tsirkin pcibus_t new_addr, last_addr; 1067315a1350SMichael S. Tsirkin int bar = pci_bar(d, reg); 1068315a1350SMichael S. Tsirkin uint16_t cmd = pci_get_word(d->config + PCI_COMMAND); 1069e4024630SLaurent Vivier Object *machine = qdev_get_machine(); 1070e4024630SLaurent Vivier ObjectClass *oc = object_get_class(machine); 1071e4024630SLaurent Vivier MachineClass *mc = MACHINE_CLASS(oc); 1072e4024630SLaurent Vivier bool allow_0_address = mc->pci_allow_0_address; 1073315a1350SMichael S. Tsirkin 1074315a1350SMichael S. Tsirkin if (type & PCI_BASE_ADDRESS_SPACE_IO) { 1075315a1350SMichael S. Tsirkin if (!(cmd & PCI_COMMAND_IO)) { 1076315a1350SMichael S. Tsirkin return PCI_BAR_UNMAPPED; 1077315a1350SMichael S. Tsirkin } 1078315a1350SMichael S. Tsirkin new_addr = pci_get_long(d->config + bar) & ~(size - 1); 1079315a1350SMichael S. Tsirkin last_addr = new_addr + size - 1; 10809f1a029aSHervé Poussineau /* Check if 32 bit BAR wraps around explicitly. 10819f1a029aSHervé Poussineau * TODO: make priorities correct and remove this work around. 10829f1a029aSHervé Poussineau */ 1083e4024630SLaurent Vivier if (last_addr <= new_addr || last_addr >= UINT32_MAX || 1084e4024630SLaurent Vivier (!allow_0_address && new_addr == 0)) { 1085315a1350SMichael S. Tsirkin return PCI_BAR_UNMAPPED; 1086315a1350SMichael S. Tsirkin } 1087315a1350SMichael S. Tsirkin return new_addr; 1088315a1350SMichael S. Tsirkin } 1089315a1350SMichael S. Tsirkin 1090315a1350SMichael S. Tsirkin if (!(cmd & PCI_COMMAND_MEMORY)) { 1091315a1350SMichael S. Tsirkin return PCI_BAR_UNMAPPED; 1092315a1350SMichael S. Tsirkin } 1093315a1350SMichael S. Tsirkin if (type & PCI_BASE_ADDRESS_MEM_TYPE_64) { 1094315a1350SMichael S. Tsirkin new_addr = pci_get_quad(d->config + bar); 1095315a1350SMichael S. Tsirkin } else { 1096315a1350SMichael S. Tsirkin new_addr = pci_get_long(d->config + bar); 1097315a1350SMichael S. Tsirkin } 1098315a1350SMichael S. Tsirkin /* the ROM slot has a specific enable bit */ 1099315a1350SMichael S. Tsirkin if (reg == PCI_ROM_SLOT && !(new_addr & PCI_ROM_ADDRESS_ENABLE)) { 1100315a1350SMichael S. Tsirkin return PCI_BAR_UNMAPPED; 1101315a1350SMichael S. Tsirkin } 1102315a1350SMichael S. Tsirkin new_addr &= ~(size - 1); 1103315a1350SMichael S. Tsirkin last_addr = new_addr + size - 1; 1104315a1350SMichael S. Tsirkin /* NOTE: we do not support wrapping */ 1105315a1350SMichael S. Tsirkin /* XXX: as we cannot support really dynamic 1106315a1350SMichael S. Tsirkin mappings, we handle specific values as invalid 1107315a1350SMichael S. Tsirkin mappings. */ 1108e4024630SLaurent Vivier if (last_addr <= new_addr || last_addr == PCI_BAR_UNMAPPED || 1109e4024630SLaurent Vivier (!allow_0_address && new_addr == 0)) { 1110315a1350SMichael S. Tsirkin return PCI_BAR_UNMAPPED; 1111315a1350SMichael S. Tsirkin } 1112315a1350SMichael S. Tsirkin 1113315a1350SMichael S. Tsirkin /* Now pcibus_t is 64bit. 1114315a1350SMichael S. Tsirkin * Check if 32 bit BAR wraps around explicitly. 1115315a1350SMichael S. Tsirkin * Without this, PC ide doesn't work well. 1116315a1350SMichael S. Tsirkin * TODO: remove this work around. 1117315a1350SMichael S. Tsirkin */ 1118315a1350SMichael S. Tsirkin if (!(type & PCI_BASE_ADDRESS_MEM_TYPE_64) && last_addr >= UINT32_MAX) { 1119315a1350SMichael S. Tsirkin return PCI_BAR_UNMAPPED; 1120315a1350SMichael S. Tsirkin } 1121315a1350SMichael S. Tsirkin 1122315a1350SMichael S. Tsirkin /* 1123315a1350SMichael S. Tsirkin * OS is allowed to set BAR beyond its addressable 1124315a1350SMichael S. Tsirkin * bits. For example, 32 bit OS can set 64bit bar 1125315a1350SMichael S. Tsirkin * to >4G. Check it. TODO: we might need to support 1126315a1350SMichael S. Tsirkin * it in the future for e.g. PAE. 1127315a1350SMichael S. Tsirkin */ 1128315a1350SMichael S. Tsirkin if (last_addr >= HWADDR_MAX) { 1129315a1350SMichael S. Tsirkin return PCI_BAR_UNMAPPED; 1130315a1350SMichael S. Tsirkin } 1131315a1350SMichael S. Tsirkin 1132315a1350SMichael S. Tsirkin return new_addr; 1133315a1350SMichael S. Tsirkin } 1134315a1350SMichael S. Tsirkin 1135315a1350SMichael S. Tsirkin static void pci_update_mappings(PCIDevice *d) 1136315a1350SMichael S. Tsirkin { 1137315a1350SMichael S. Tsirkin PCIIORegion *r; 1138315a1350SMichael S. Tsirkin int i; 1139315a1350SMichael S. Tsirkin pcibus_t new_addr; 1140315a1350SMichael S. Tsirkin 1141315a1350SMichael S. Tsirkin for(i = 0; i < PCI_NUM_REGIONS; i++) { 1142315a1350SMichael S. Tsirkin r = &d->io_regions[i]; 1143315a1350SMichael S. Tsirkin 1144315a1350SMichael S. Tsirkin /* this region isn't registered */ 1145315a1350SMichael S. Tsirkin if (!r->size) 1146315a1350SMichael S. Tsirkin continue; 1147315a1350SMichael S. Tsirkin 1148315a1350SMichael S. Tsirkin new_addr = pci_bar_address(d, i, r->type, r->size); 1149315a1350SMichael S. Tsirkin 1150315a1350SMichael S. Tsirkin /* This bar isn't changed */ 1151315a1350SMichael S. Tsirkin if (new_addr == r->addr) 1152315a1350SMichael S. Tsirkin continue; 1153315a1350SMichael S. Tsirkin 1154315a1350SMichael S. Tsirkin /* now do the real mapping */ 1155315a1350SMichael S. Tsirkin if (r->addr != PCI_BAR_UNMAPPED) { 11567828d750SDon Koch trace_pci_update_mappings_del(d, pci_bus_num(d->bus), 11577828d750SDon Koch PCI_FUNC(d->devfn), 11587828d750SDon Koch PCI_SLOT(d->devfn), 11597828d750SDon Koch i, r->addr, r->size); 1160315a1350SMichael S. Tsirkin memory_region_del_subregion(r->address_space, r->memory); 1161315a1350SMichael S. Tsirkin } 1162315a1350SMichael S. Tsirkin r->addr = new_addr; 1163315a1350SMichael S. Tsirkin if (r->addr != PCI_BAR_UNMAPPED) { 11647828d750SDon Koch trace_pci_update_mappings_add(d, pci_bus_num(d->bus), 11657828d750SDon Koch PCI_FUNC(d->devfn), 11667828d750SDon Koch PCI_SLOT(d->devfn), 11677828d750SDon Koch i, r->addr, r->size); 1168315a1350SMichael S. Tsirkin memory_region_add_subregion_overlap(r->address_space, 1169315a1350SMichael S. Tsirkin r->addr, r->memory, 1); 1170315a1350SMichael S. Tsirkin } 1171315a1350SMichael S. Tsirkin } 1172e01fd687SAlex Williamson 1173e01fd687SAlex Williamson pci_update_vga(d); 1174315a1350SMichael S. Tsirkin } 1175315a1350SMichael S. Tsirkin 1176315a1350SMichael S. Tsirkin static inline int pci_irq_disabled(PCIDevice *d) 1177315a1350SMichael S. Tsirkin { 1178315a1350SMichael S. Tsirkin return pci_get_word(d->config + PCI_COMMAND) & PCI_COMMAND_INTX_DISABLE; 1179315a1350SMichael S. Tsirkin } 1180315a1350SMichael S. Tsirkin 1181315a1350SMichael S. Tsirkin /* Called after interrupt disabled field update in config space, 1182315a1350SMichael S. Tsirkin * assert/deassert interrupts if necessary. 1183315a1350SMichael S. Tsirkin * Gets original interrupt disable bit value (before update). */ 1184315a1350SMichael S. Tsirkin static void pci_update_irq_disabled(PCIDevice *d, int was_irq_disabled) 1185315a1350SMichael S. Tsirkin { 1186315a1350SMichael S. Tsirkin int i, disabled = pci_irq_disabled(d); 1187315a1350SMichael S. Tsirkin if (disabled == was_irq_disabled) 1188315a1350SMichael S. Tsirkin return; 1189315a1350SMichael S. Tsirkin for (i = 0; i < PCI_NUM_PINS; ++i) { 1190315a1350SMichael S. Tsirkin int state = pci_irq_state(d, i); 1191315a1350SMichael S. Tsirkin pci_change_irq_level(d, i, disabled ? -state : state); 1192315a1350SMichael S. Tsirkin } 1193315a1350SMichael S. Tsirkin } 1194315a1350SMichael S. Tsirkin 1195315a1350SMichael S. Tsirkin uint32_t pci_default_read_config(PCIDevice *d, 1196315a1350SMichael S. Tsirkin uint32_t address, int len) 1197315a1350SMichael S. Tsirkin { 1198315a1350SMichael S. Tsirkin uint32_t val = 0; 1199315a1350SMichael S. Tsirkin 1200315a1350SMichael S. Tsirkin memcpy(&val, d->config + address, len); 1201315a1350SMichael S. Tsirkin return le32_to_cpu(val); 1202315a1350SMichael S. Tsirkin } 1203315a1350SMichael S. Tsirkin 1204d7efb7e0SKnut Omang void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val_in, int l) 1205315a1350SMichael S. Tsirkin { 1206315a1350SMichael S. Tsirkin int i, was_irq_disabled = pci_irq_disabled(d); 1207d7efb7e0SKnut Omang uint32_t val = val_in; 1208315a1350SMichael S. Tsirkin 1209315a1350SMichael S. Tsirkin for (i = 0; i < l; val >>= 8, ++i) { 1210315a1350SMichael S. Tsirkin uint8_t wmask = d->wmask[addr + i]; 1211315a1350SMichael S. Tsirkin uint8_t w1cmask = d->w1cmask[addr + i]; 1212315a1350SMichael S. Tsirkin assert(!(wmask & w1cmask)); 1213315a1350SMichael S. Tsirkin d->config[addr + i] = (d->config[addr + i] & ~wmask) | (val & wmask); 1214315a1350SMichael S. Tsirkin d->config[addr + i] &= ~(val & w1cmask); /* W1C: Write 1 to Clear */ 1215315a1350SMichael S. Tsirkin } 1216315a1350SMichael S. Tsirkin if (ranges_overlap(addr, l, PCI_BASE_ADDRESS_0, 24) || 1217315a1350SMichael S. Tsirkin ranges_overlap(addr, l, PCI_ROM_ADDRESS, 4) || 1218315a1350SMichael S. Tsirkin ranges_overlap(addr, l, PCI_ROM_ADDRESS1, 4) || 1219315a1350SMichael S. Tsirkin range_covers_byte(addr, l, PCI_COMMAND)) 1220315a1350SMichael S. Tsirkin pci_update_mappings(d); 1221315a1350SMichael S. Tsirkin 1222315a1350SMichael S. Tsirkin if (range_covers_byte(addr, l, PCI_COMMAND)) { 1223315a1350SMichael S. Tsirkin pci_update_irq_disabled(d, was_irq_disabled); 1224315a1350SMichael S. Tsirkin memory_region_set_enabled(&d->bus_master_enable_region, 1225315a1350SMichael S. Tsirkin pci_get_word(d->config + PCI_COMMAND) 1226315a1350SMichael S. Tsirkin & PCI_COMMAND_MASTER); 1227315a1350SMichael S. Tsirkin } 1228315a1350SMichael S. Tsirkin 1229d7efb7e0SKnut Omang msi_write_config(d, addr, val_in, l); 1230d7efb7e0SKnut Omang msix_write_config(d, addr, val_in, l); 1231315a1350SMichael S. Tsirkin } 1232315a1350SMichael S. Tsirkin 1233315a1350SMichael S. Tsirkin /***********************************************************/ 1234315a1350SMichael S. Tsirkin /* generic PCI irq support */ 1235315a1350SMichael S. Tsirkin 1236315a1350SMichael S. Tsirkin /* 0 <= irq_num <= 3. level must be 0 or 1 */ 1237d98f08f5SMarcel Apfelbaum static void pci_irq_handler(void *opaque, int irq_num, int level) 1238315a1350SMichael S. Tsirkin { 1239315a1350SMichael S. Tsirkin PCIDevice *pci_dev = opaque; 1240315a1350SMichael S. Tsirkin int change; 1241315a1350SMichael S. Tsirkin 1242315a1350SMichael S. Tsirkin change = level - pci_irq_state(pci_dev, irq_num); 1243315a1350SMichael S. Tsirkin if (!change) 1244315a1350SMichael S. Tsirkin return; 1245315a1350SMichael S. Tsirkin 1246315a1350SMichael S. Tsirkin pci_set_irq_state(pci_dev, irq_num, level); 1247315a1350SMichael S. Tsirkin pci_update_irq_status(pci_dev); 1248315a1350SMichael S. Tsirkin if (pci_irq_disabled(pci_dev)) 1249315a1350SMichael S. Tsirkin return; 1250315a1350SMichael S. Tsirkin pci_change_irq_level(pci_dev, irq_num, change); 1251315a1350SMichael S. Tsirkin } 1252315a1350SMichael S. Tsirkin 1253d98f08f5SMarcel Apfelbaum static inline int pci_intx(PCIDevice *pci_dev) 1254d98f08f5SMarcel Apfelbaum { 1255d98f08f5SMarcel Apfelbaum return pci_get_byte(pci_dev->config + PCI_INTERRUPT_PIN) - 1; 1256d98f08f5SMarcel Apfelbaum } 1257d98f08f5SMarcel Apfelbaum 1258d98f08f5SMarcel Apfelbaum qemu_irq pci_allocate_irq(PCIDevice *pci_dev) 1259d98f08f5SMarcel Apfelbaum { 1260d98f08f5SMarcel Apfelbaum int intx = pci_intx(pci_dev); 1261d98f08f5SMarcel Apfelbaum 1262d98f08f5SMarcel Apfelbaum return qemu_allocate_irq(pci_irq_handler, pci_dev, intx); 1263d98f08f5SMarcel Apfelbaum } 1264d98f08f5SMarcel Apfelbaum 1265d98f08f5SMarcel Apfelbaum void pci_set_irq(PCIDevice *pci_dev, int level) 1266d98f08f5SMarcel Apfelbaum { 1267d98f08f5SMarcel Apfelbaum int intx = pci_intx(pci_dev); 1268d98f08f5SMarcel Apfelbaum pci_irq_handler(pci_dev, intx, level); 1269d98f08f5SMarcel Apfelbaum } 1270d98f08f5SMarcel Apfelbaum 1271315a1350SMichael S. Tsirkin /* Special hooks used by device assignment */ 1272315a1350SMichael S. Tsirkin void pci_bus_set_route_irq_fn(PCIBus *bus, pci_route_irq_fn route_intx_to_irq) 1273315a1350SMichael S. Tsirkin { 12740889464aSAlex Williamson assert(pci_bus_is_root(bus)); 1275315a1350SMichael S. Tsirkin bus->route_intx_to_irq = route_intx_to_irq; 1276315a1350SMichael S. Tsirkin } 1277315a1350SMichael S. Tsirkin 1278315a1350SMichael S. Tsirkin PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin) 1279315a1350SMichael S. Tsirkin { 1280315a1350SMichael S. Tsirkin PCIBus *bus; 1281315a1350SMichael S. Tsirkin 1282315a1350SMichael S. Tsirkin do { 1283315a1350SMichael S. Tsirkin bus = dev->bus; 1284315a1350SMichael S. Tsirkin pin = bus->map_irq(dev, pin); 1285315a1350SMichael S. Tsirkin dev = bus->parent_dev; 1286315a1350SMichael S. Tsirkin } while (dev); 1287315a1350SMichael S. Tsirkin 1288315a1350SMichael S. Tsirkin if (!bus->route_intx_to_irq) { 1289312fd5f2SMarkus Armbruster error_report("PCI: Bug - unimplemented PCI INTx routing (%s)", 1290315a1350SMichael S. Tsirkin object_get_typename(OBJECT(bus->qbus.parent))); 1291315a1350SMichael S. Tsirkin return (PCIINTxRoute) { PCI_INTX_DISABLED, -1 }; 1292315a1350SMichael S. Tsirkin } 1293315a1350SMichael S. Tsirkin 1294315a1350SMichael S. Tsirkin return bus->route_intx_to_irq(bus->irq_opaque, pin); 1295315a1350SMichael S. Tsirkin } 1296315a1350SMichael S. Tsirkin 1297315a1350SMichael S. Tsirkin bool pci_intx_route_changed(PCIINTxRoute *old, PCIINTxRoute *new) 1298315a1350SMichael S. Tsirkin { 1299315a1350SMichael S. Tsirkin return old->mode != new->mode || old->irq != new->irq; 1300315a1350SMichael S. Tsirkin } 1301315a1350SMichael S. Tsirkin 1302315a1350SMichael S. Tsirkin void pci_bus_fire_intx_routing_notifier(PCIBus *bus) 1303315a1350SMichael S. Tsirkin { 1304315a1350SMichael S. Tsirkin PCIDevice *dev; 1305315a1350SMichael S. Tsirkin PCIBus *sec; 1306315a1350SMichael S. Tsirkin int i; 1307315a1350SMichael S. Tsirkin 1308315a1350SMichael S. Tsirkin for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) { 1309315a1350SMichael S. Tsirkin dev = bus->devices[i]; 1310315a1350SMichael S. Tsirkin if (dev && dev->intx_routing_notifier) { 1311315a1350SMichael S. Tsirkin dev->intx_routing_notifier(dev); 1312315a1350SMichael S. Tsirkin } 1313e5368f0dSAlex Williamson } 1314e5368f0dSAlex Williamson 1315315a1350SMichael S. Tsirkin QLIST_FOREACH(sec, &bus->child, sibling) { 1316315a1350SMichael S. Tsirkin pci_bus_fire_intx_routing_notifier(sec); 1317315a1350SMichael S. Tsirkin } 1318315a1350SMichael S. Tsirkin } 1319315a1350SMichael S. Tsirkin 1320315a1350SMichael S. Tsirkin void pci_device_set_intx_routing_notifier(PCIDevice *dev, 1321315a1350SMichael S. Tsirkin PCIINTxRoutingNotifier notifier) 1322315a1350SMichael S. Tsirkin { 1323315a1350SMichael S. Tsirkin dev->intx_routing_notifier = notifier; 1324315a1350SMichael S. Tsirkin } 1325315a1350SMichael S. Tsirkin 1326315a1350SMichael S. Tsirkin /* 1327315a1350SMichael S. Tsirkin * PCI-to-PCI bridge specification 1328315a1350SMichael S. Tsirkin * 9.1: Interrupt routing. Table 9-1 1329315a1350SMichael S. Tsirkin * 1330315a1350SMichael S. Tsirkin * the PCI Express Base Specification, Revision 2.1 1331315a1350SMichael S. Tsirkin * 2.2.8.1: INTx interrutp signaling - Rules 1332315a1350SMichael S. Tsirkin * the Implementation Note 1333315a1350SMichael S. Tsirkin * Table 2-20 1334315a1350SMichael S. Tsirkin */ 1335315a1350SMichael S. Tsirkin /* 1336315a1350SMichael S. Tsirkin * 0 <= pin <= 3 0 = INTA, 1 = INTB, 2 = INTC, 3 = INTD 1337315a1350SMichael S. Tsirkin * 0-origin unlike PCI interrupt pin register. 1338315a1350SMichael S. Tsirkin */ 1339315a1350SMichael S. Tsirkin int pci_swizzle_map_irq_fn(PCIDevice *pci_dev, int pin) 1340315a1350SMichael S. Tsirkin { 1341315a1350SMichael S. Tsirkin return (pin + PCI_SLOT(pci_dev->devfn)) % PCI_NUM_PINS; 1342315a1350SMichael S. Tsirkin } 1343315a1350SMichael S. Tsirkin 1344315a1350SMichael S. Tsirkin /***********************************************************/ 1345315a1350SMichael S. Tsirkin /* monitor info on PCI */ 1346315a1350SMichael S. Tsirkin 1347315a1350SMichael S. Tsirkin typedef struct { 1348315a1350SMichael S. Tsirkin uint16_t class; 1349315a1350SMichael S. Tsirkin const char *desc; 1350315a1350SMichael S. Tsirkin const char *fw_name; 1351315a1350SMichael S. Tsirkin uint16_t fw_ign_bits; 1352315a1350SMichael S. Tsirkin } pci_class_desc; 1353315a1350SMichael S. Tsirkin 1354315a1350SMichael S. Tsirkin static const pci_class_desc pci_class_descriptions[] = 1355315a1350SMichael S. Tsirkin { 1356315a1350SMichael S. Tsirkin { 0x0001, "VGA controller", "display"}, 1357315a1350SMichael S. Tsirkin { 0x0100, "SCSI controller", "scsi"}, 1358315a1350SMichael S. Tsirkin { 0x0101, "IDE controller", "ide"}, 1359315a1350SMichael S. Tsirkin { 0x0102, "Floppy controller", "fdc"}, 1360315a1350SMichael S. Tsirkin { 0x0103, "IPI controller", "ipi"}, 1361315a1350SMichael S. Tsirkin { 0x0104, "RAID controller", "raid"}, 1362315a1350SMichael S. Tsirkin { 0x0106, "SATA controller"}, 1363315a1350SMichael S. Tsirkin { 0x0107, "SAS controller"}, 1364315a1350SMichael S. Tsirkin { 0x0180, "Storage controller"}, 1365315a1350SMichael S. Tsirkin { 0x0200, "Ethernet controller", "ethernet"}, 1366315a1350SMichael S. Tsirkin { 0x0201, "Token Ring controller", "token-ring"}, 1367315a1350SMichael S. Tsirkin { 0x0202, "FDDI controller", "fddi"}, 1368315a1350SMichael S. Tsirkin { 0x0203, "ATM controller", "atm"}, 1369315a1350SMichael S. Tsirkin { 0x0280, "Network controller"}, 1370315a1350SMichael S. Tsirkin { 0x0300, "VGA controller", "display", 0x00ff}, 1371315a1350SMichael S. Tsirkin { 0x0301, "XGA controller"}, 1372315a1350SMichael S. Tsirkin { 0x0302, "3D controller"}, 1373315a1350SMichael S. Tsirkin { 0x0380, "Display controller"}, 1374315a1350SMichael S. Tsirkin { 0x0400, "Video controller", "video"}, 1375315a1350SMichael S. Tsirkin { 0x0401, "Audio controller", "sound"}, 1376315a1350SMichael S. Tsirkin { 0x0402, "Phone"}, 1377315a1350SMichael S. Tsirkin { 0x0403, "Audio controller", "sound"}, 1378315a1350SMichael S. Tsirkin { 0x0480, "Multimedia controller"}, 1379315a1350SMichael S. Tsirkin { 0x0500, "RAM controller", "memory"}, 1380315a1350SMichael S. Tsirkin { 0x0501, "Flash controller", "flash"}, 1381315a1350SMichael S. Tsirkin { 0x0580, "Memory controller"}, 1382315a1350SMichael S. Tsirkin { 0x0600, "Host bridge", "host"}, 1383315a1350SMichael S. Tsirkin { 0x0601, "ISA bridge", "isa"}, 1384315a1350SMichael S. Tsirkin { 0x0602, "EISA bridge", "eisa"}, 1385315a1350SMichael S. Tsirkin { 0x0603, "MC bridge", "mca"}, 13864c41425dSGerd Hoffmann { 0x0604, "PCI bridge", "pci-bridge"}, 1387315a1350SMichael S. Tsirkin { 0x0605, "PCMCIA bridge", "pcmcia"}, 1388315a1350SMichael S. Tsirkin { 0x0606, "NUBUS bridge", "nubus"}, 1389315a1350SMichael S. Tsirkin { 0x0607, "CARDBUS bridge", "cardbus"}, 1390315a1350SMichael S. Tsirkin { 0x0608, "RACEWAY bridge"}, 1391315a1350SMichael S. Tsirkin { 0x0680, "Bridge"}, 1392315a1350SMichael S. Tsirkin { 0x0700, "Serial port", "serial"}, 1393315a1350SMichael S. Tsirkin { 0x0701, "Parallel port", "parallel"}, 1394315a1350SMichael S. Tsirkin { 0x0800, "Interrupt controller", "interrupt-controller"}, 1395315a1350SMichael S. Tsirkin { 0x0801, "DMA controller", "dma-controller"}, 1396315a1350SMichael S. Tsirkin { 0x0802, "Timer", "timer"}, 1397315a1350SMichael S. Tsirkin { 0x0803, "RTC", "rtc"}, 1398315a1350SMichael S. Tsirkin { 0x0900, "Keyboard", "keyboard"}, 1399315a1350SMichael S. Tsirkin { 0x0901, "Pen", "pen"}, 1400315a1350SMichael S. Tsirkin { 0x0902, "Mouse", "mouse"}, 1401315a1350SMichael S. Tsirkin { 0x0A00, "Dock station", "dock", 0x00ff}, 1402315a1350SMichael S. Tsirkin { 0x0B00, "i386 cpu", "cpu", 0x00ff}, 1403315a1350SMichael S. Tsirkin { 0x0c00, "Fireware contorller", "fireware"}, 1404315a1350SMichael S. Tsirkin { 0x0c01, "Access bus controller", "access-bus"}, 1405315a1350SMichael S. Tsirkin { 0x0c02, "SSA controller", "ssa"}, 1406315a1350SMichael S. Tsirkin { 0x0c03, "USB controller", "usb"}, 1407315a1350SMichael S. Tsirkin { 0x0c04, "Fibre channel controller", "fibre-channel"}, 1408315a1350SMichael S. Tsirkin { 0x0c05, "SMBus"}, 1409315a1350SMichael S. Tsirkin { 0, NULL} 1410315a1350SMichael S. Tsirkin }; 1411315a1350SMichael S. Tsirkin 1412315a1350SMichael S. Tsirkin static void pci_for_each_device_under_bus(PCIBus *bus, 1413315a1350SMichael S. Tsirkin void (*fn)(PCIBus *b, PCIDevice *d, 1414315a1350SMichael S. Tsirkin void *opaque), 1415315a1350SMichael S. Tsirkin void *opaque) 1416315a1350SMichael S. Tsirkin { 1417315a1350SMichael S. Tsirkin PCIDevice *d; 1418315a1350SMichael S. Tsirkin int devfn; 1419315a1350SMichael S. Tsirkin 1420315a1350SMichael S. Tsirkin for(devfn = 0; devfn < ARRAY_SIZE(bus->devices); devfn++) { 1421315a1350SMichael S. Tsirkin d = bus->devices[devfn]; 1422315a1350SMichael S. Tsirkin if (d) { 1423315a1350SMichael S. Tsirkin fn(bus, d, opaque); 1424315a1350SMichael S. Tsirkin } 1425315a1350SMichael S. Tsirkin } 1426315a1350SMichael S. Tsirkin } 1427315a1350SMichael S. Tsirkin 1428315a1350SMichael S. Tsirkin void pci_for_each_device(PCIBus *bus, int bus_num, 1429315a1350SMichael S. Tsirkin void (*fn)(PCIBus *b, PCIDevice *d, void *opaque), 1430315a1350SMichael S. Tsirkin void *opaque) 1431315a1350SMichael S. Tsirkin { 1432315a1350SMichael S. Tsirkin bus = pci_find_bus_nr(bus, bus_num); 1433315a1350SMichael S. Tsirkin 1434315a1350SMichael S. Tsirkin if (bus) { 1435315a1350SMichael S. Tsirkin pci_for_each_device_under_bus(bus, fn, opaque); 1436315a1350SMichael S. Tsirkin } 1437315a1350SMichael S. Tsirkin } 1438315a1350SMichael S. Tsirkin 1439315a1350SMichael S. Tsirkin static const pci_class_desc *get_class_desc(int class) 1440315a1350SMichael S. Tsirkin { 1441315a1350SMichael S. Tsirkin const pci_class_desc *desc; 1442315a1350SMichael S. Tsirkin 1443315a1350SMichael S. Tsirkin desc = pci_class_descriptions; 1444315a1350SMichael S. Tsirkin while (desc->desc && class != desc->class) { 1445315a1350SMichael S. Tsirkin desc++; 1446315a1350SMichael S. Tsirkin } 1447315a1350SMichael S. Tsirkin 1448315a1350SMichael S. Tsirkin return desc; 1449315a1350SMichael S. Tsirkin } 1450315a1350SMichael S. Tsirkin 1451315a1350SMichael S. Tsirkin static PciDeviceInfoList *qmp_query_pci_devices(PCIBus *bus, int bus_num); 1452315a1350SMichael S. Tsirkin 1453315a1350SMichael S. Tsirkin static PciMemoryRegionList *qmp_query_pci_regions(const PCIDevice *dev) 1454315a1350SMichael S. Tsirkin { 1455315a1350SMichael S. Tsirkin PciMemoryRegionList *head = NULL, *cur_item = NULL; 1456315a1350SMichael S. Tsirkin int i; 1457315a1350SMichael S. Tsirkin 1458315a1350SMichael S. Tsirkin for (i = 0; i < PCI_NUM_REGIONS; i++) { 1459315a1350SMichael S. Tsirkin const PCIIORegion *r = &dev->io_regions[i]; 1460315a1350SMichael S. Tsirkin PciMemoryRegionList *region; 1461315a1350SMichael S. Tsirkin 1462315a1350SMichael S. Tsirkin if (!r->size) { 1463315a1350SMichael S. Tsirkin continue; 1464315a1350SMichael S. Tsirkin } 1465315a1350SMichael S. Tsirkin 1466315a1350SMichael S. Tsirkin region = g_malloc0(sizeof(*region)); 1467315a1350SMichael S. Tsirkin region->value = g_malloc0(sizeof(*region->value)); 1468315a1350SMichael S. Tsirkin 1469315a1350SMichael S. Tsirkin if (r->type & PCI_BASE_ADDRESS_SPACE_IO) { 1470315a1350SMichael S. Tsirkin region->value->type = g_strdup("io"); 1471315a1350SMichael S. Tsirkin } else { 1472315a1350SMichael S. Tsirkin region->value->type = g_strdup("memory"); 1473315a1350SMichael S. Tsirkin region->value->has_prefetch = true; 1474315a1350SMichael S. Tsirkin region->value->prefetch = !!(r->type & PCI_BASE_ADDRESS_MEM_PREFETCH); 1475315a1350SMichael S. Tsirkin region->value->has_mem_type_64 = true; 1476315a1350SMichael S. Tsirkin region->value->mem_type_64 = !!(r->type & PCI_BASE_ADDRESS_MEM_TYPE_64); 1477315a1350SMichael S. Tsirkin } 1478315a1350SMichael S. Tsirkin 1479315a1350SMichael S. Tsirkin region->value->bar = i; 1480315a1350SMichael S. Tsirkin region->value->address = r->addr; 1481315a1350SMichael S. Tsirkin region->value->size = r->size; 1482315a1350SMichael S. Tsirkin 1483315a1350SMichael S. Tsirkin /* XXX: waiting for the qapi to support GSList */ 1484315a1350SMichael S. Tsirkin if (!cur_item) { 1485315a1350SMichael S. Tsirkin head = cur_item = region; 1486315a1350SMichael S. Tsirkin } else { 1487315a1350SMichael S. Tsirkin cur_item->next = region; 1488315a1350SMichael S. Tsirkin cur_item = region; 1489315a1350SMichael S. Tsirkin } 1490315a1350SMichael S. Tsirkin } 1491315a1350SMichael S. Tsirkin 1492315a1350SMichael S. Tsirkin return head; 1493315a1350SMichael S. Tsirkin } 1494315a1350SMichael S. Tsirkin 1495315a1350SMichael S. Tsirkin static PciBridgeInfo *qmp_query_pci_bridge(PCIDevice *dev, PCIBus *bus, 1496315a1350SMichael S. Tsirkin int bus_num) 1497315a1350SMichael S. Tsirkin { 1498315a1350SMichael S. Tsirkin PciBridgeInfo *info; 14999fa02cd1SEric Blake PciMemoryRange *range; 1500315a1350SMichael S. Tsirkin 15019fa02cd1SEric Blake info = g_new0(PciBridgeInfo, 1); 1502315a1350SMichael S. Tsirkin 15039fa02cd1SEric Blake info->bus = g_new0(PciBusInfo, 1); 15049fa02cd1SEric Blake info->bus->number = dev->config[PCI_PRIMARY_BUS]; 15059fa02cd1SEric Blake info->bus->secondary = dev->config[PCI_SECONDARY_BUS]; 15069fa02cd1SEric Blake info->bus->subordinate = dev->config[PCI_SUBORDINATE_BUS]; 1507315a1350SMichael S. Tsirkin 15089fa02cd1SEric Blake range = info->bus->io_range = g_new0(PciMemoryRange, 1); 15099fa02cd1SEric Blake range->base = pci_bridge_get_base(dev, PCI_BASE_ADDRESS_SPACE_IO); 15109fa02cd1SEric Blake range->limit = pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_SPACE_IO); 1511315a1350SMichael S. Tsirkin 15129fa02cd1SEric Blake range = info->bus->memory_range = g_new0(PciMemoryRange, 1); 15139fa02cd1SEric Blake range->base = pci_bridge_get_base(dev, PCI_BASE_ADDRESS_SPACE_MEMORY); 15149fa02cd1SEric Blake range->limit = pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_SPACE_MEMORY); 1515315a1350SMichael S. Tsirkin 15169fa02cd1SEric Blake range = info->bus->prefetchable_range = g_new0(PciMemoryRange, 1); 15179fa02cd1SEric Blake range->base = pci_bridge_get_base(dev, PCI_BASE_ADDRESS_MEM_PREFETCH); 15189fa02cd1SEric Blake range->limit = pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_MEM_PREFETCH); 1519315a1350SMichael S. Tsirkin 1520315a1350SMichael S. Tsirkin if (dev->config[PCI_SECONDARY_BUS] != 0) { 1521315a1350SMichael S. Tsirkin PCIBus *child_bus = pci_find_bus_nr(bus, dev->config[PCI_SECONDARY_BUS]); 1522315a1350SMichael S. Tsirkin if (child_bus) { 1523315a1350SMichael S. Tsirkin info->has_devices = true; 1524315a1350SMichael S. Tsirkin info->devices = qmp_query_pci_devices(child_bus, dev->config[PCI_SECONDARY_BUS]); 1525315a1350SMichael S. Tsirkin } 1526315a1350SMichael S. Tsirkin } 1527315a1350SMichael S. Tsirkin 1528315a1350SMichael S. Tsirkin return info; 1529315a1350SMichael S. Tsirkin } 1530315a1350SMichael S. Tsirkin 1531315a1350SMichael S. Tsirkin static PciDeviceInfo *qmp_query_pci_device(PCIDevice *dev, PCIBus *bus, 1532315a1350SMichael S. Tsirkin int bus_num) 1533315a1350SMichael S. Tsirkin { 1534315a1350SMichael S. Tsirkin const pci_class_desc *desc; 1535315a1350SMichael S. Tsirkin PciDeviceInfo *info; 1536315a1350SMichael S. Tsirkin uint8_t type; 1537315a1350SMichael S. Tsirkin int class; 1538315a1350SMichael S. Tsirkin 15399fa02cd1SEric Blake info = g_new0(PciDeviceInfo, 1); 1540315a1350SMichael S. Tsirkin info->bus = bus_num; 1541315a1350SMichael S. Tsirkin info->slot = PCI_SLOT(dev->devfn); 1542315a1350SMichael S. Tsirkin info->function = PCI_FUNC(dev->devfn); 1543315a1350SMichael S. Tsirkin 15449fa02cd1SEric Blake info->class_info = g_new0(PciDeviceClass, 1); 1545315a1350SMichael S. Tsirkin class = pci_get_word(dev->config + PCI_CLASS_DEVICE); 15469fa02cd1SEric Blake info->class_info->q_class = class; 1547315a1350SMichael S. Tsirkin desc = get_class_desc(class); 1548315a1350SMichael S. Tsirkin if (desc->desc) { 15499fa02cd1SEric Blake info->class_info->has_desc = true; 15509fa02cd1SEric Blake info->class_info->desc = g_strdup(desc->desc); 1551315a1350SMichael S. Tsirkin } 1552315a1350SMichael S. Tsirkin 15539fa02cd1SEric Blake info->id = g_new0(PciDeviceId, 1); 15549fa02cd1SEric Blake info->id->vendor = pci_get_word(dev->config + PCI_VENDOR_ID); 15559fa02cd1SEric Blake info->id->device = pci_get_word(dev->config + PCI_DEVICE_ID); 1556315a1350SMichael S. Tsirkin info->regions = qmp_query_pci_regions(dev); 1557315a1350SMichael S. Tsirkin info->qdev_id = g_strdup(dev->qdev.id ? dev->qdev.id : ""); 1558315a1350SMichael S. Tsirkin 1559315a1350SMichael S. Tsirkin if (dev->config[PCI_INTERRUPT_PIN] != 0) { 1560315a1350SMichael S. Tsirkin info->has_irq = true; 1561315a1350SMichael S. Tsirkin info->irq = dev->config[PCI_INTERRUPT_LINE]; 1562315a1350SMichael S. Tsirkin } 1563315a1350SMichael S. Tsirkin 1564315a1350SMichael S. Tsirkin type = dev->config[PCI_HEADER_TYPE] & ~PCI_HEADER_TYPE_MULTI_FUNCTION; 1565315a1350SMichael S. Tsirkin if (type == PCI_HEADER_TYPE_BRIDGE) { 1566315a1350SMichael S. Tsirkin info->has_pci_bridge = true; 1567315a1350SMichael S. Tsirkin info->pci_bridge = qmp_query_pci_bridge(dev, bus, bus_num); 1568315a1350SMichael S. Tsirkin } 1569315a1350SMichael S. Tsirkin 1570315a1350SMichael S. Tsirkin return info; 1571315a1350SMichael S. Tsirkin } 1572315a1350SMichael S. Tsirkin 1573315a1350SMichael S. Tsirkin static PciDeviceInfoList *qmp_query_pci_devices(PCIBus *bus, int bus_num) 1574315a1350SMichael S. Tsirkin { 1575315a1350SMichael S. Tsirkin PciDeviceInfoList *info, *head = NULL, *cur_item = NULL; 1576315a1350SMichael S. Tsirkin PCIDevice *dev; 1577315a1350SMichael S. Tsirkin int devfn; 1578315a1350SMichael S. Tsirkin 1579315a1350SMichael S. Tsirkin for (devfn = 0; devfn < ARRAY_SIZE(bus->devices); devfn++) { 1580315a1350SMichael S. Tsirkin dev = bus->devices[devfn]; 1581315a1350SMichael S. Tsirkin if (dev) { 1582315a1350SMichael S. Tsirkin info = g_malloc0(sizeof(*info)); 1583315a1350SMichael S. Tsirkin info->value = qmp_query_pci_device(dev, bus, bus_num); 1584315a1350SMichael S. Tsirkin 1585315a1350SMichael S. Tsirkin /* XXX: waiting for the qapi to support GSList */ 1586315a1350SMichael S. Tsirkin if (!cur_item) { 1587315a1350SMichael S. Tsirkin head = cur_item = info; 1588315a1350SMichael S. Tsirkin } else { 1589315a1350SMichael S. Tsirkin cur_item->next = info; 1590315a1350SMichael S. Tsirkin cur_item = info; 1591315a1350SMichael S. Tsirkin } 1592315a1350SMichael S. Tsirkin } 1593315a1350SMichael S. Tsirkin } 1594315a1350SMichael S. Tsirkin 1595315a1350SMichael S. Tsirkin return head; 1596315a1350SMichael S. Tsirkin } 1597315a1350SMichael S. Tsirkin 1598315a1350SMichael S. Tsirkin static PciInfo *qmp_query_pci_bus(PCIBus *bus, int bus_num) 1599315a1350SMichael S. Tsirkin { 1600315a1350SMichael S. Tsirkin PciInfo *info = NULL; 1601315a1350SMichael S. Tsirkin 1602315a1350SMichael S. Tsirkin bus = pci_find_bus_nr(bus, bus_num); 1603315a1350SMichael S. Tsirkin if (bus) { 1604315a1350SMichael S. Tsirkin info = g_malloc0(sizeof(*info)); 1605315a1350SMichael S. Tsirkin info->bus = bus_num; 1606315a1350SMichael S. Tsirkin info->devices = qmp_query_pci_devices(bus, bus_num); 1607315a1350SMichael S. Tsirkin } 1608315a1350SMichael S. Tsirkin 1609315a1350SMichael S. Tsirkin return info; 1610315a1350SMichael S. Tsirkin } 1611315a1350SMichael S. Tsirkin 1612315a1350SMichael S. Tsirkin PciInfoList *qmp_query_pci(Error **errp) 1613315a1350SMichael S. Tsirkin { 1614315a1350SMichael S. Tsirkin PciInfoList *info, *head = NULL, *cur_item = NULL; 16157588e2b0SDavid Gibson PCIHostState *host_bridge; 1616315a1350SMichael S. Tsirkin 16177588e2b0SDavid Gibson QLIST_FOREACH(host_bridge, &pci_host_bridges, next) { 1618315a1350SMichael S. Tsirkin info = g_malloc0(sizeof(*info)); 1619cb2ed8b3SMarcel Apfelbaum info->value = qmp_query_pci_bus(host_bridge->bus, 1620cb2ed8b3SMarcel Apfelbaum pci_bus_num(host_bridge->bus)); 1621315a1350SMichael S. Tsirkin 1622315a1350SMichael S. Tsirkin /* XXX: waiting for the qapi to support GSList */ 1623315a1350SMichael S. Tsirkin if (!cur_item) { 1624315a1350SMichael S. Tsirkin head = cur_item = info; 1625315a1350SMichael S. Tsirkin } else { 1626315a1350SMichael S. Tsirkin cur_item->next = info; 1627315a1350SMichael S. Tsirkin cur_item = info; 1628315a1350SMichael S. Tsirkin } 1629315a1350SMichael S. Tsirkin } 1630315a1350SMichael S. Tsirkin 1631315a1350SMichael S. Tsirkin return head; 1632315a1350SMichael S. Tsirkin } 1633315a1350SMichael S. Tsirkin 1634315a1350SMichael S. Tsirkin static const char * const pci_nic_models[] = { 1635315a1350SMichael S. Tsirkin "ne2k_pci", 1636315a1350SMichael S. Tsirkin "i82551", 1637315a1350SMichael S. Tsirkin "i82557b", 1638315a1350SMichael S. Tsirkin "i82559er", 1639315a1350SMichael S. Tsirkin "rtl8139", 1640315a1350SMichael S. Tsirkin "e1000", 1641315a1350SMichael S. Tsirkin "pcnet", 1642315a1350SMichael S. Tsirkin "virtio", 1643315a1350SMichael S. Tsirkin NULL 1644315a1350SMichael S. Tsirkin }; 1645315a1350SMichael S. Tsirkin 1646315a1350SMichael S. Tsirkin static const char * const pci_nic_names[] = { 1647315a1350SMichael S. Tsirkin "ne2k_pci", 1648315a1350SMichael S. Tsirkin "i82551", 1649315a1350SMichael S. Tsirkin "i82557b", 1650315a1350SMichael S. Tsirkin "i82559er", 1651315a1350SMichael S. Tsirkin "rtl8139", 1652315a1350SMichael S. Tsirkin "e1000", 1653315a1350SMichael S. Tsirkin "pcnet", 1654315a1350SMichael S. Tsirkin "virtio-net-pci", 1655315a1350SMichael S. Tsirkin NULL 1656315a1350SMichael S. Tsirkin }; 1657315a1350SMichael S. Tsirkin 1658315a1350SMichael S. Tsirkin /* Initialize a PCI NIC. */ 165951f7cb97SThomas Huth PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus, 166029b358f9SDavid Gibson const char *default_model, 166151f7cb97SThomas Huth const char *default_devaddr) 1662315a1350SMichael S. Tsirkin { 1663315a1350SMichael S. Tsirkin const char *devaddr = nd->devaddr ? nd->devaddr : default_devaddr; 1664558ecef2SMarkus Armbruster Error *err = NULL; 1665315a1350SMichael S. Tsirkin PCIBus *bus; 1666315a1350SMichael S. Tsirkin PCIDevice *pci_dev; 1667315a1350SMichael S. Tsirkin DeviceState *dev; 166851f7cb97SThomas Huth int devfn; 1669315a1350SMichael S. Tsirkin int i; 1670315a1350SMichael S. Tsirkin 167151f7cb97SThomas Huth if (qemu_show_nic_models(nd->model, pci_nic_models)) { 167251f7cb97SThomas Huth exit(0); 167351f7cb97SThomas Huth } 167451f7cb97SThomas Huth 1675315a1350SMichael S. Tsirkin i = qemu_find_nic_model(nd, pci_nic_models, default_model); 167651f7cb97SThomas Huth if (i < 0) { 167751f7cb97SThomas Huth exit(1); 167851f7cb97SThomas Huth } 1679315a1350SMichael S. Tsirkin 168029b358f9SDavid Gibson bus = pci_get_bus_devfn(&devfn, rootbus, devaddr); 1681315a1350SMichael S. Tsirkin if (!bus) { 1682315a1350SMichael S. Tsirkin error_report("Invalid PCI device address %s for device %s", 1683315a1350SMichael S. Tsirkin devaddr, pci_nic_names[i]); 168451f7cb97SThomas Huth exit(1); 1685315a1350SMichael S. Tsirkin } 1686315a1350SMichael S. Tsirkin 1687315a1350SMichael S. Tsirkin pci_dev = pci_create(bus, devfn, pci_nic_names[i]); 1688315a1350SMichael S. Tsirkin dev = &pci_dev->qdev; 1689315a1350SMichael S. Tsirkin qdev_set_nic_properties(dev, nd); 1690558ecef2SMarkus Armbruster 1691558ecef2SMarkus Armbruster object_property_set_bool(OBJECT(dev), true, "realized", &err); 1692558ecef2SMarkus Armbruster if (err) { 1693558ecef2SMarkus Armbruster error_report_err(err); 169451f7cb97SThomas Huth object_unparent(OBJECT(dev)); 1695315a1350SMichael S. Tsirkin exit(1); 1696558ecef2SMarkus Armbruster } 169751f7cb97SThomas Huth 169851f7cb97SThomas Huth return pci_dev; 1699315a1350SMichael S. Tsirkin } 1700315a1350SMichael S. Tsirkin 1701315a1350SMichael S. Tsirkin PCIDevice *pci_vga_init(PCIBus *bus) 1702315a1350SMichael S. Tsirkin { 1703315a1350SMichael S. Tsirkin switch (vga_interface_type) { 1704315a1350SMichael S. Tsirkin case VGA_CIRRUS: 1705315a1350SMichael S. Tsirkin return pci_create_simple(bus, -1, "cirrus-vga"); 1706315a1350SMichael S. Tsirkin case VGA_QXL: 1707315a1350SMichael S. Tsirkin return pci_create_simple(bus, -1, "qxl-vga"); 1708315a1350SMichael S. Tsirkin case VGA_STD: 1709315a1350SMichael S. Tsirkin return pci_create_simple(bus, -1, "VGA"); 1710315a1350SMichael S. Tsirkin case VGA_VMWARE: 1711315a1350SMichael S. Tsirkin return pci_create_simple(bus, -1, "vmware-svga"); 1712a94f0c5cSGerd Hoffmann case VGA_VIRTIO: 1713a94f0c5cSGerd Hoffmann return pci_create_simple(bus, -1, "virtio-vga"); 1714315a1350SMichael S. Tsirkin case VGA_NONE: 1715315a1350SMichael S. Tsirkin default: /* Other non-PCI types. Checking for unsupported types is already 1716315a1350SMichael S. Tsirkin done in vl.c. */ 1717315a1350SMichael S. Tsirkin return NULL; 1718315a1350SMichael S. Tsirkin } 1719315a1350SMichael S. Tsirkin } 1720315a1350SMichael S. Tsirkin 1721315a1350SMichael S. Tsirkin /* Whether a given bus number is in range of the secondary 1722315a1350SMichael S. Tsirkin * bus of the given bridge device. */ 1723315a1350SMichael S. Tsirkin static bool pci_secondary_bus_in_range(PCIDevice *dev, int bus_num) 1724315a1350SMichael S. Tsirkin { 1725315a1350SMichael S. Tsirkin return !(pci_get_word(dev->config + PCI_BRIDGE_CONTROL) & 1726315a1350SMichael S. Tsirkin PCI_BRIDGE_CTL_BUS_RESET) /* Don't walk the bus if it's reset. */ && 172709e5b819SMarcel Apfelbaum dev->config[PCI_SECONDARY_BUS] <= bus_num && 1728315a1350SMichael S. Tsirkin bus_num <= dev->config[PCI_SUBORDINATE_BUS]; 1729315a1350SMichael S. Tsirkin } 1730315a1350SMichael S. Tsirkin 173109e5b819SMarcel Apfelbaum /* Whether a given bus number is in a range of a root bus */ 173209e5b819SMarcel Apfelbaum static bool pci_root_bus_in_range(PCIBus *bus, int bus_num) 173309e5b819SMarcel Apfelbaum { 173409e5b819SMarcel Apfelbaum int i; 173509e5b819SMarcel Apfelbaum 173609e5b819SMarcel Apfelbaum for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) { 173709e5b819SMarcel Apfelbaum PCIDevice *dev = bus->devices[i]; 173809e5b819SMarcel Apfelbaum 173909e5b819SMarcel Apfelbaum if (dev && PCI_DEVICE_GET_CLASS(dev)->is_bridge) { 174009e5b819SMarcel Apfelbaum if (pci_secondary_bus_in_range(dev, bus_num)) { 174109e5b819SMarcel Apfelbaum return true; 174209e5b819SMarcel Apfelbaum } 174309e5b819SMarcel Apfelbaum } 174409e5b819SMarcel Apfelbaum } 174509e5b819SMarcel Apfelbaum 174609e5b819SMarcel Apfelbaum return false; 174709e5b819SMarcel Apfelbaum } 174809e5b819SMarcel Apfelbaum 1749315a1350SMichael S. Tsirkin static PCIBus *pci_find_bus_nr(PCIBus *bus, int bus_num) 1750315a1350SMichael S. Tsirkin { 1751315a1350SMichael S. Tsirkin PCIBus *sec; 1752315a1350SMichael S. Tsirkin 1753315a1350SMichael S. Tsirkin if (!bus) { 1754315a1350SMichael S. Tsirkin return NULL; 1755315a1350SMichael S. Tsirkin } 1756315a1350SMichael S. Tsirkin 1757315a1350SMichael S. Tsirkin if (pci_bus_num(bus) == bus_num) { 1758315a1350SMichael S. Tsirkin return bus; 1759315a1350SMichael S. Tsirkin } 1760315a1350SMichael S. Tsirkin 1761315a1350SMichael S. Tsirkin /* Consider all bus numbers in range for the host pci bridge. */ 17620889464aSAlex Williamson if (!pci_bus_is_root(bus) && 1763315a1350SMichael S. Tsirkin !pci_secondary_bus_in_range(bus->parent_dev, bus_num)) { 1764315a1350SMichael S. Tsirkin return NULL; 1765315a1350SMichael S. Tsirkin } 1766315a1350SMichael S. Tsirkin 1767315a1350SMichael S. Tsirkin /* try child bus */ 1768315a1350SMichael S. Tsirkin for (; bus; bus = sec) { 1769315a1350SMichael S. Tsirkin QLIST_FOREACH(sec, &bus->child, sibling) { 177009e5b819SMarcel Apfelbaum if (pci_bus_num(sec) == bus_num) { 1771315a1350SMichael S. Tsirkin return sec; 1772315a1350SMichael S. Tsirkin } 177309e5b819SMarcel Apfelbaum /* PXB buses assumed to be children of bus 0 */ 177409e5b819SMarcel Apfelbaum if (pci_bus_is_root(sec)) { 177509e5b819SMarcel Apfelbaum if (pci_root_bus_in_range(sec, bus_num)) { 177609e5b819SMarcel Apfelbaum break; 177709e5b819SMarcel Apfelbaum } 177809e5b819SMarcel Apfelbaum } else { 1779315a1350SMichael S. Tsirkin if (pci_secondary_bus_in_range(sec->parent_dev, bus_num)) { 1780315a1350SMichael S. Tsirkin break; 1781315a1350SMichael S. Tsirkin } 1782315a1350SMichael S. Tsirkin } 1783315a1350SMichael S. Tsirkin } 178409e5b819SMarcel Apfelbaum } 1785315a1350SMichael S. Tsirkin 1786315a1350SMichael S. Tsirkin return NULL; 1787315a1350SMichael S. Tsirkin } 1788315a1350SMichael S. Tsirkin 1789eb0acfddSMichael S. Tsirkin void pci_for_each_bus_depth_first(PCIBus *bus, 1790eb0acfddSMichael S. Tsirkin void *(*begin)(PCIBus *bus, void *parent_state), 1791eb0acfddSMichael S. Tsirkin void (*end)(PCIBus *bus, void *state), 1792eb0acfddSMichael S. Tsirkin void *parent_state) 1793eb0acfddSMichael S. Tsirkin { 1794eb0acfddSMichael S. Tsirkin PCIBus *sec; 1795eb0acfddSMichael S. Tsirkin void *state; 1796eb0acfddSMichael S. Tsirkin 1797eb0acfddSMichael S. Tsirkin if (!bus) { 1798eb0acfddSMichael S. Tsirkin return; 1799eb0acfddSMichael S. Tsirkin } 1800eb0acfddSMichael S. Tsirkin 1801eb0acfddSMichael S. Tsirkin if (begin) { 1802eb0acfddSMichael S. Tsirkin state = begin(bus, parent_state); 1803eb0acfddSMichael S. Tsirkin } else { 1804eb0acfddSMichael S. Tsirkin state = parent_state; 1805eb0acfddSMichael S. Tsirkin } 1806eb0acfddSMichael S. Tsirkin 1807eb0acfddSMichael S. Tsirkin QLIST_FOREACH(sec, &bus->child, sibling) { 1808eb0acfddSMichael S. Tsirkin pci_for_each_bus_depth_first(sec, begin, end, state); 1809eb0acfddSMichael S. Tsirkin } 1810eb0acfddSMichael S. Tsirkin 1811eb0acfddSMichael S. Tsirkin if (end) { 1812eb0acfddSMichael S. Tsirkin end(bus, state); 1813eb0acfddSMichael S. Tsirkin } 1814eb0acfddSMichael S. Tsirkin } 1815eb0acfddSMichael S. Tsirkin 1816eb0acfddSMichael S. Tsirkin 1817315a1350SMichael S. Tsirkin PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn) 1818315a1350SMichael S. Tsirkin { 1819315a1350SMichael S. Tsirkin bus = pci_find_bus_nr(bus, bus_num); 1820315a1350SMichael S. Tsirkin 1821315a1350SMichael S. Tsirkin if (!bus) 1822315a1350SMichael S. Tsirkin return NULL; 1823315a1350SMichael S. Tsirkin 1824315a1350SMichael S. Tsirkin return bus->devices[devfn]; 1825315a1350SMichael S. Tsirkin } 1826315a1350SMichael S. Tsirkin 1827133e9b22SMarkus Armbruster static void pci_qdev_realize(DeviceState *qdev, Error **errp) 1828315a1350SMichael S. Tsirkin { 1829315a1350SMichael S. Tsirkin PCIDevice *pci_dev = (PCIDevice *)qdev; 1830315a1350SMichael S. Tsirkin PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev); 1831133e9b22SMarkus Armbruster Error *local_err = NULL; 1832315a1350SMichael S. Tsirkin PCIBus *bus; 1833315a1350SMichael S. Tsirkin bool is_default_rom; 1834315a1350SMichael S. Tsirkin 1835315a1350SMichael S. Tsirkin /* initialize cap_present for pci_is_express() and pci_config_size() */ 1836315a1350SMichael S. Tsirkin if (pc->is_express) { 1837315a1350SMichael S. Tsirkin pci_dev->cap_present |= QEMU_PCI_CAP_EXPRESS; 1838315a1350SMichael S. Tsirkin } 1839315a1350SMichael S. Tsirkin 1840fef7fbc9SAndreas Färber bus = PCI_BUS(qdev_get_parent_bus(qdev)); 1841315a1350SMichael S. Tsirkin pci_dev = do_pci_register_device(pci_dev, bus, 1842315a1350SMichael S. Tsirkin object_get_typename(OBJECT(qdev)), 1843133e9b22SMarkus Armbruster pci_dev->devfn, errp); 1844315a1350SMichael S. Tsirkin if (pci_dev == NULL) 1845133e9b22SMarkus Armbruster return; 18462897ae02SIgor Mammedov 18477ee6c1e1SMarkus Armbruster if (pc->realize) { 18487ee6c1e1SMarkus Armbruster pc->realize(pci_dev, &local_err); 18497ee6c1e1SMarkus Armbruster if (local_err) { 18507ee6c1e1SMarkus Armbruster error_propagate(errp, local_err); 1851315a1350SMichael S. Tsirkin do_pci_unregister_device(pci_dev); 1852133e9b22SMarkus Armbruster return; 1853315a1350SMichael S. Tsirkin } 1854315a1350SMichael S. Tsirkin } 1855315a1350SMichael S. Tsirkin 1856315a1350SMichael S. Tsirkin /* rom loading */ 1857315a1350SMichael S. Tsirkin is_default_rom = false; 1858315a1350SMichael S. Tsirkin if (pci_dev->romfile == NULL && pc->romfile != NULL) { 1859315a1350SMichael S. Tsirkin pci_dev->romfile = g_strdup(pc->romfile); 1860315a1350SMichael S. Tsirkin is_default_rom = true; 1861315a1350SMichael S. Tsirkin } 1862178e785fSMarcel Apfelbaum 1863133e9b22SMarkus Armbruster pci_add_option_rom(pci_dev, is_default_rom, &local_err); 1864133e9b22SMarkus Armbruster if (local_err) { 1865133e9b22SMarkus Armbruster error_propagate(errp, local_err); 1866133e9b22SMarkus Armbruster pci_qdev_unrealize(DEVICE(pci_dev), NULL); 1867133e9b22SMarkus Armbruster return; 1868178e785fSMarcel Apfelbaum } 1869315a1350SMichael S. Tsirkin } 1870315a1350SMichael S. Tsirkin 18717ee6c1e1SMarkus Armbruster static void pci_default_realize(PCIDevice *dev, Error **errp) 18727ee6c1e1SMarkus Armbruster { 18737ee6c1e1SMarkus Armbruster PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev); 18747ee6c1e1SMarkus Armbruster 18757ee6c1e1SMarkus Armbruster if (pc->init) { 18767ee6c1e1SMarkus Armbruster if (pc->init(dev) < 0) { 18777ee6c1e1SMarkus Armbruster error_setg(errp, "Device initialization failed"); 18787ee6c1e1SMarkus Armbruster return; 18797ee6c1e1SMarkus Armbruster } 18807ee6c1e1SMarkus Armbruster } 18817ee6c1e1SMarkus Armbruster } 18827ee6c1e1SMarkus Armbruster 1883315a1350SMichael S. Tsirkin PCIDevice *pci_create_multifunction(PCIBus *bus, int devfn, bool multifunction, 1884315a1350SMichael S. Tsirkin const char *name) 1885315a1350SMichael S. Tsirkin { 1886315a1350SMichael S. Tsirkin DeviceState *dev; 1887315a1350SMichael S. Tsirkin 1888315a1350SMichael S. Tsirkin dev = qdev_create(&bus->qbus, name); 1889315a1350SMichael S. Tsirkin qdev_prop_set_int32(dev, "addr", devfn); 1890315a1350SMichael S. Tsirkin qdev_prop_set_bit(dev, "multifunction", multifunction); 1891315a1350SMichael S. Tsirkin return PCI_DEVICE(dev); 1892315a1350SMichael S. Tsirkin } 1893315a1350SMichael S. Tsirkin 1894315a1350SMichael S. Tsirkin PCIDevice *pci_create_simple_multifunction(PCIBus *bus, int devfn, 1895315a1350SMichael S. Tsirkin bool multifunction, 1896315a1350SMichael S. Tsirkin const char *name) 1897315a1350SMichael S. Tsirkin { 1898315a1350SMichael S. Tsirkin PCIDevice *dev = pci_create_multifunction(bus, devfn, multifunction, name); 1899315a1350SMichael S. Tsirkin qdev_init_nofail(&dev->qdev); 1900315a1350SMichael S. Tsirkin return dev; 1901315a1350SMichael S. Tsirkin } 1902315a1350SMichael S. Tsirkin 1903315a1350SMichael S. Tsirkin PCIDevice *pci_create(PCIBus *bus, int devfn, const char *name) 1904315a1350SMichael S. Tsirkin { 1905315a1350SMichael S. Tsirkin return pci_create_multifunction(bus, devfn, false, name); 1906315a1350SMichael S. Tsirkin } 1907315a1350SMichael S. Tsirkin 1908315a1350SMichael S. Tsirkin PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name) 1909315a1350SMichael S. Tsirkin { 1910315a1350SMichael S. Tsirkin return pci_create_simple_multifunction(bus, devfn, false, name); 1911315a1350SMichael S. Tsirkin } 1912315a1350SMichael S. Tsirkin 1913315a1350SMichael S. Tsirkin static uint8_t pci_find_space(PCIDevice *pdev, uint8_t size) 1914315a1350SMichael S. Tsirkin { 1915315a1350SMichael S. Tsirkin int offset = PCI_CONFIG_HEADER_SIZE; 1916315a1350SMichael S. Tsirkin int i; 1917315a1350SMichael S. Tsirkin for (i = PCI_CONFIG_HEADER_SIZE; i < PCI_CONFIG_SPACE_SIZE; ++i) { 1918315a1350SMichael S. Tsirkin if (pdev->used[i]) 1919315a1350SMichael S. Tsirkin offset = i + 1; 1920315a1350SMichael S. Tsirkin else if (i - offset + 1 == size) 1921315a1350SMichael S. Tsirkin return offset; 1922315a1350SMichael S. Tsirkin } 1923315a1350SMichael S. Tsirkin return 0; 1924315a1350SMichael S. Tsirkin } 1925315a1350SMichael S. Tsirkin 1926315a1350SMichael S. Tsirkin static uint8_t pci_find_capability_list(PCIDevice *pdev, uint8_t cap_id, 1927315a1350SMichael S. Tsirkin uint8_t *prev_p) 1928315a1350SMichael S. Tsirkin { 1929315a1350SMichael S. Tsirkin uint8_t next, prev; 1930315a1350SMichael S. Tsirkin 1931315a1350SMichael S. Tsirkin if (!(pdev->config[PCI_STATUS] & PCI_STATUS_CAP_LIST)) 1932315a1350SMichael S. Tsirkin return 0; 1933315a1350SMichael S. Tsirkin 1934315a1350SMichael S. Tsirkin for (prev = PCI_CAPABILITY_LIST; (next = pdev->config[prev]); 1935315a1350SMichael S. Tsirkin prev = next + PCI_CAP_LIST_NEXT) 1936315a1350SMichael S. Tsirkin if (pdev->config[next + PCI_CAP_LIST_ID] == cap_id) 1937315a1350SMichael S. Tsirkin break; 1938315a1350SMichael S. Tsirkin 1939315a1350SMichael S. Tsirkin if (prev_p) 1940315a1350SMichael S. Tsirkin *prev_p = prev; 1941315a1350SMichael S. Tsirkin return next; 1942315a1350SMichael S. Tsirkin } 1943315a1350SMichael S. Tsirkin 1944315a1350SMichael S. Tsirkin static uint8_t pci_find_capability_at_offset(PCIDevice *pdev, uint8_t offset) 1945315a1350SMichael S. Tsirkin { 1946315a1350SMichael S. Tsirkin uint8_t next, prev, found = 0; 1947315a1350SMichael S. Tsirkin 1948315a1350SMichael S. Tsirkin if (!(pdev->used[offset])) { 1949315a1350SMichael S. Tsirkin return 0; 1950315a1350SMichael S. Tsirkin } 1951315a1350SMichael S. Tsirkin 1952315a1350SMichael S. Tsirkin assert(pdev->config[PCI_STATUS] & PCI_STATUS_CAP_LIST); 1953315a1350SMichael S. Tsirkin 1954315a1350SMichael S. Tsirkin for (prev = PCI_CAPABILITY_LIST; (next = pdev->config[prev]); 1955315a1350SMichael S. Tsirkin prev = next + PCI_CAP_LIST_NEXT) { 1956315a1350SMichael S. Tsirkin if (next <= offset && next > found) { 1957315a1350SMichael S. Tsirkin found = next; 1958315a1350SMichael S. Tsirkin } 1959315a1350SMichael S. Tsirkin } 1960315a1350SMichael S. Tsirkin return found; 1961315a1350SMichael S. Tsirkin } 1962315a1350SMichael S. Tsirkin 1963315a1350SMichael S. Tsirkin /* Patch the PCI vendor and device ids in a PCI rom image if necessary. 1964315a1350SMichael S. Tsirkin This is needed for an option rom which is used for more than one device. */ 1965315a1350SMichael S. Tsirkin static void pci_patch_ids(PCIDevice *pdev, uint8_t *ptr, int size) 1966315a1350SMichael S. Tsirkin { 1967315a1350SMichael S. Tsirkin uint16_t vendor_id; 1968315a1350SMichael S. Tsirkin uint16_t device_id; 1969315a1350SMichael S. Tsirkin uint16_t rom_vendor_id; 1970315a1350SMichael S. Tsirkin uint16_t rom_device_id; 1971315a1350SMichael S. Tsirkin uint16_t rom_magic; 1972315a1350SMichael S. Tsirkin uint16_t pcir_offset; 1973315a1350SMichael S. Tsirkin uint8_t checksum; 1974315a1350SMichael S. Tsirkin 1975315a1350SMichael S. Tsirkin /* Words in rom data are little endian (like in PCI configuration), 1976315a1350SMichael S. Tsirkin so they can be read / written with pci_get_word / pci_set_word. */ 1977315a1350SMichael S. Tsirkin 1978315a1350SMichael S. Tsirkin /* Only a valid rom will be patched. */ 1979315a1350SMichael S. Tsirkin rom_magic = pci_get_word(ptr); 1980315a1350SMichael S. Tsirkin if (rom_magic != 0xaa55) { 1981315a1350SMichael S. Tsirkin PCI_DPRINTF("Bad ROM magic %04x\n", rom_magic); 1982315a1350SMichael S. Tsirkin return; 1983315a1350SMichael S. Tsirkin } 1984315a1350SMichael S. Tsirkin pcir_offset = pci_get_word(ptr + 0x18); 1985315a1350SMichael S. Tsirkin if (pcir_offset + 8 >= size || memcmp(ptr + pcir_offset, "PCIR", 4)) { 1986315a1350SMichael S. Tsirkin PCI_DPRINTF("Bad PCIR offset 0x%x or signature\n", pcir_offset); 1987315a1350SMichael S. Tsirkin return; 1988315a1350SMichael S. Tsirkin } 1989315a1350SMichael S. Tsirkin 1990315a1350SMichael S. Tsirkin vendor_id = pci_get_word(pdev->config + PCI_VENDOR_ID); 1991315a1350SMichael S. Tsirkin device_id = pci_get_word(pdev->config + PCI_DEVICE_ID); 1992315a1350SMichael S. Tsirkin rom_vendor_id = pci_get_word(ptr + pcir_offset + 4); 1993315a1350SMichael S. Tsirkin rom_device_id = pci_get_word(ptr + pcir_offset + 6); 1994315a1350SMichael S. Tsirkin 1995315a1350SMichael S. Tsirkin PCI_DPRINTF("%s: ROM id %04x%04x / PCI id %04x%04x\n", pdev->romfile, 1996315a1350SMichael S. Tsirkin vendor_id, device_id, rom_vendor_id, rom_device_id); 1997315a1350SMichael S. Tsirkin 1998315a1350SMichael S. Tsirkin checksum = ptr[6]; 1999315a1350SMichael S. Tsirkin 2000315a1350SMichael S. Tsirkin if (vendor_id != rom_vendor_id) { 2001315a1350SMichael S. Tsirkin /* Patch vendor id and checksum (at offset 6 for etherboot roms). */ 2002315a1350SMichael S. Tsirkin checksum += (uint8_t)rom_vendor_id + (uint8_t)(rom_vendor_id >> 8); 2003315a1350SMichael S. Tsirkin checksum -= (uint8_t)vendor_id + (uint8_t)(vendor_id >> 8); 2004315a1350SMichael S. Tsirkin PCI_DPRINTF("ROM checksum %02x / %02x\n", ptr[6], checksum); 2005315a1350SMichael S. Tsirkin ptr[6] = checksum; 2006315a1350SMichael S. Tsirkin pci_set_word(ptr + pcir_offset + 4, vendor_id); 2007315a1350SMichael S. Tsirkin } 2008315a1350SMichael S. Tsirkin 2009315a1350SMichael S. Tsirkin if (device_id != rom_device_id) { 2010315a1350SMichael S. Tsirkin /* Patch device id and checksum (at offset 6 for etherboot roms). */ 2011315a1350SMichael S. Tsirkin checksum += (uint8_t)rom_device_id + (uint8_t)(rom_device_id >> 8); 2012315a1350SMichael S. Tsirkin checksum -= (uint8_t)device_id + (uint8_t)(device_id >> 8); 2013315a1350SMichael S. Tsirkin PCI_DPRINTF("ROM checksum %02x / %02x\n", ptr[6], checksum); 2014315a1350SMichael S. Tsirkin ptr[6] = checksum; 2015315a1350SMichael S. Tsirkin pci_set_word(ptr + pcir_offset + 6, device_id); 2016315a1350SMichael S. Tsirkin } 2017315a1350SMichael S. Tsirkin } 2018315a1350SMichael S. Tsirkin 2019315a1350SMichael S. Tsirkin /* Add an option rom for the device */ 2020133e9b22SMarkus Armbruster static void pci_add_option_rom(PCIDevice *pdev, bool is_default_rom, 2021133e9b22SMarkus Armbruster Error **errp) 2022315a1350SMichael S. Tsirkin { 2023315a1350SMichael S. Tsirkin int size; 2024315a1350SMichael S. Tsirkin char *path; 2025315a1350SMichael S. Tsirkin void *ptr; 2026315a1350SMichael S. Tsirkin char name[32]; 2027315a1350SMichael S. Tsirkin const VMStateDescription *vmsd; 2028315a1350SMichael S. Tsirkin 2029315a1350SMichael S. Tsirkin if (!pdev->romfile) 2030133e9b22SMarkus Armbruster return; 2031315a1350SMichael S. Tsirkin if (strlen(pdev->romfile) == 0) 2032133e9b22SMarkus Armbruster return; 2033315a1350SMichael S. Tsirkin 2034315a1350SMichael S. Tsirkin if (!pdev->rom_bar) { 2035315a1350SMichael S. Tsirkin /* 2036315a1350SMichael S. Tsirkin * Load rom via fw_cfg instead of creating a rom bar, 2037315a1350SMichael S. Tsirkin * for 0.11 compatibility. 2038315a1350SMichael S. Tsirkin */ 2039315a1350SMichael S. Tsirkin int class = pci_get_word(pdev->config + PCI_CLASS_DEVICE); 2040db80c7b9SMarcel Apfelbaum 2041db80c7b9SMarcel Apfelbaum /* 2042db80c7b9SMarcel Apfelbaum * Hot-plugged devices can't use the option ROM 2043db80c7b9SMarcel Apfelbaum * if the rom bar is disabled. 2044db80c7b9SMarcel Apfelbaum */ 2045db80c7b9SMarcel Apfelbaum if (DEVICE(pdev)->hotplugged) { 2046133e9b22SMarkus Armbruster error_setg(errp, "Hot-plugged device without ROM bar" 2047133e9b22SMarkus Armbruster " can't have an option ROM"); 2048133e9b22SMarkus Armbruster return; 2049db80c7b9SMarcel Apfelbaum } 2050db80c7b9SMarcel Apfelbaum 2051315a1350SMichael S. Tsirkin if (class == 0x0300) { 2052315a1350SMichael S. Tsirkin rom_add_vga(pdev->romfile); 2053315a1350SMichael S. Tsirkin } else { 2054315a1350SMichael S. Tsirkin rom_add_option(pdev->romfile, -1); 2055315a1350SMichael S. Tsirkin } 2056133e9b22SMarkus Armbruster return; 2057315a1350SMichael S. Tsirkin } 2058315a1350SMichael S. Tsirkin 2059315a1350SMichael S. Tsirkin path = qemu_find_file(QEMU_FILE_TYPE_BIOS, pdev->romfile); 2060315a1350SMichael S. Tsirkin if (path == NULL) { 2061315a1350SMichael S. Tsirkin path = g_strdup(pdev->romfile); 2062315a1350SMichael S. Tsirkin } 2063315a1350SMichael S. Tsirkin 2064315a1350SMichael S. Tsirkin size = get_image_size(path); 2065315a1350SMichael S. Tsirkin if (size < 0) { 2066133e9b22SMarkus Armbruster error_setg(errp, "failed to find romfile \"%s\"", pdev->romfile); 20678c7f3dd0SStefan Hajnoczi g_free(path); 2068133e9b22SMarkus Armbruster return; 20698c7f3dd0SStefan Hajnoczi } else if (size == 0) { 2070133e9b22SMarkus Armbruster error_setg(errp, "romfile \"%s\" is empty", pdev->romfile); 2071315a1350SMichael S. Tsirkin g_free(path); 2072133e9b22SMarkus Armbruster return; 2073315a1350SMichael S. Tsirkin } 2074*9bff5d81SPeter Maydell size = pow2ceil(size); 2075315a1350SMichael S. Tsirkin 2076315a1350SMichael S. Tsirkin vmsd = qdev_get_vmsd(DEVICE(pdev)); 2077315a1350SMichael S. Tsirkin 2078315a1350SMichael S. Tsirkin if (vmsd) { 2079315a1350SMichael S. Tsirkin snprintf(name, sizeof(name), "%s.rom", vmsd->name); 2080315a1350SMichael S. Tsirkin } else { 2081315a1350SMichael S. Tsirkin snprintf(name, sizeof(name), "%s.rom", object_get_typename(OBJECT(pdev))); 2082315a1350SMichael S. Tsirkin } 2083315a1350SMichael S. Tsirkin pdev->has_rom = true; 208449946538SHu Tao memory_region_init_ram(&pdev->rom, OBJECT(pdev), name, size, &error_abort); 2085315a1350SMichael S. Tsirkin vmstate_register_ram(&pdev->rom, &pdev->qdev); 2086315a1350SMichael S. Tsirkin ptr = memory_region_get_ram_ptr(&pdev->rom); 2087315a1350SMichael S. Tsirkin load_image(path, ptr); 2088315a1350SMichael S. Tsirkin g_free(path); 2089315a1350SMichael S. Tsirkin 2090315a1350SMichael S. Tsirkin if (is_default_rom) { 2091315a1350SMichael S. Tsirkin /* Only the default rom images will be patched (if needed). */ 2092315a1350SMichael S. Tsirkin pci_patch_ids(pdev, ptr, size); 2093315a1350SMichael S. Tsirkin } 2094315a1350SMichael S. Tsirkin 2095315a1350SMichael S. Tsirkin pci_register_bar(pdev, PCI_ROM_SLOT, 0, &pdev->rom); 2096315a1350SMichael S. Tsirkin } 2097315a1350SMichael S. Tsirkin 2098315a1350SMichael S. Tsirkin static void pci_del_option_rom(PCIDevice *pdev) 2099315a1350SMichael S. Tsirkin { 2100315a1350SMichael S. Tsirkin if (!pdev->has_rom) 2101315a1350SMichael S. Tsirkin return; 2102315a1350SMichael S. Tsirkin 2103315a1350SMichael S. Tsirkin vmstate_unregister_ram(&pdev->rom, &pdev->qdev); 2104315a1350SMichael S. Tsirkin pdev->has_rom = false; 2105315a1350SMichael S. Tsirkin } 2106315a1350SMichael S. Tsirkin 2107315a1350SMichael S. Tsirkin /* 2108315a1350SMichael S. Tsirkin * if offset = 0, 2109315a1350SMichael S. Tsirkin * Find and reserve space and add capability to the linked list 21109a2a6623SChen Hanxiao * in pci config space 21119a2a6623SChen Hanxiao */ 2112315a1350SMichael S. Tsirkin int pci_add_capability(PCIDevice *pdev, uint8_t cap_id, 2113315a1350SMichael S. Tsirkin uint8_t offset, uint8_t size) 2114315a1350SMichael S. Tsirkin { 2115cd9aa33eSLaszlo Ersek int ret; 2116cd9aa33eSLaszlo Ersek Error *local_err = NULL; 2117cd9aa33eSLaszlo Ersek 2118cd9aa33eSLaszlo Ersek ret = pci_add_capability2(pdev, cap_id, offset, size, &local_err); 2119cd9aa33eSLaszlo Ersek if (local_err) { 2120cd9aa33eSLaszlo Ersek assert(ret < 0); 2121565f65d2SMarkus Armbruster error_report_err(local_err); 2122cd9aa33eSLaszlo Ersek } else { 2123cd9aa33eSLaszlo Ersek /* success implies a positive offset in config space */ 2124cd9aa33eSLaszlo Ersek assert(ret > 0); 2125cd9aa33eSLaszlo Ersek } 2126cd9aa33eSLaszlo Ersek return ret; 2127cd9aa33eSLaszlo Ersek } 2128cd9aa33eSLaszlo Ersek 2129cd9aa33eSLaszlo Ersek int pci_add_capability2(PCIDevice *pdev, uint8_t cap_id, 2130cd9aa33eSLaszlo Ersek uint8_t offset, uint8_t size, 2131cd9aa33eSLaszlo Ersek Error **errp) 2132cd9aa33eSLaszlo Ersek { 2133315a1350SMichael S. Tsirkin uint8_t *config; 2134315a1350SMichael S. Tsirkin int i, overlapping_cap; 2135315a1350SMichael S. Tsirkin 2136315a1350SMichael S. Tsirkin if (!offset) { 2137315a1350SMichael S. Tsirkin offset = pci_find_space(pdev, size); 2138315a1350SMichael S. Tsirkin if (!offset) { 2139cd9aa33eSLaszlo Ersek error_setg(errp, "out of PCI config space"); 2140315a1350SMichael S. Tsirkin return -ENOSPC; 2141315a1350SMichael S. Tsirkin } 2142315a1350SMichael S. Tsirkin } else { 2143315a1350SMichael S. Tsirkin /* Verify that capabilities don't overlap. Note: device assignment 2144315a1350SMichael S. Tsirkin * depends on this check to verify that the device is not broken. 2145315a1350SMichael S. Tsirkin * Should never trigger for emulated devices, but it's helpful 2146315a1350SMichael S. Tsirkin * for debugging these. */ 2147315a1350SMichael S. Tsirkin for (i = offset; i < offset + size; i++) { 2148315a1350SMichael S. Tsirkin overlapping_cap = pci_find_capability_at_offset(pdev, i); 2149315a1350SMichael S. Tsirkin if (overlapping_cap) { 2150cd9aa33eSLaszlo Ersek error_setg(errp, "%s:%02x:%02x.%x " 2151315a1350SMichael S. Tsirkin "Attempt to add PCI capability %x at offset " 2152cd9aa33eSLaszlo Ersek "%x overlaps existing capability %x at offset %x", 2153568f0690SDavid Gibson pci_root_bus_path(pdev), pci_bus_num(pdev->bus), 2154315a1350SMichael S. Tsirkin PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), 2155315a1350SMichael S. Tsirkin cap_id, offset, overlapping_cap, i); 2156315a1350SMichael S. Tsirkin return -EINVAL; 2157315a1350SMichael S. Tsirkin } 2158315a1350SMichael S. Tsirkin } 2159315a1350SMichael S. Tsirkin } 2160315a1350SMichael S. Tsirkin 2161315a1350SMichael S. Tsirkin config = pdev->config + offset; 2162315a1350SMichael S. Tsirkin config[PCI_CAP_LIST_ID] = cap_id; 2163315a1350SMichael S. Tsirkin config[PCI_CAP_LIST_NEXT] = pdev->config[PCI_CAPABILITY_LIST]; 2164315a1350SMichael S. Tsirkin pdev->config[PCI_CAPABILITY_LIST] = offset; 2165315a1350SMichael S. Tsirkin pdev->config[PCI_STATUS] |= PCI_STATUS_CAP_LIST; 2166315a1350SMichael S. Tsirkin memset(pdev->used + offset, 0xFF, QEMU_ALIGN_UP(size, 4)); 2167315a1350SMichael S. Tsirkin /* Make capability read-only by default */ 2168315a1350SMichael S. Tsirkin memset(pdev->wmask + offset, 0, size); 2169315a1350SMichael S. Tsirkin /* Check capability by default */ 2170315a1350SMichael S. Tsirkin memset(pdev->cmask + offset, 0xFF, size); 2171315a1350SMichael S. Tsirkin return offset; 2172315a1350SMichael S. Tsirkin } 2173315a1350SMichael S. Tsirkin 2174315a1350SMichael S. Tsirkin /* Unlink capability from the pci config space. */ 2175315a1350SMichael S. Tsirkin void pci_del_capability(PCIDevice *pdev, uint8_t cap_id, uint8_t size) 2176315a1350SMichael S. Tsirkin { 2177315a1350SMichael S. Tsirkin uint8_t prev, offset = pci_find_capability_list(pdev, cap_id, &prev); 2178315a1350SMichael S. Tsirkin if (!offset) 2179315a1350SMichael S. Tsirkin return; 2180315a1350SMichael S. Tsirkin pdev->config[prev] = pdev->config[offset + PCI_CAP_LIST_NEXT]; 2181315a1350SMichael S. Tsirkin /* Make capability writable again */ 2182315a1350SMichael S. Tsirkin memset(pdev->wmask + offset, 0xff, size); 2183315a1350SMichael S. Tsirkin memset(pdev->w1cmask + offset, 0, size); 2184315a1350SMichael S. Tsirkin /* Clear cmask as device-specific registers can't be checked */ 2185315a1350SMichael S. Tsirkin memset(pdev->cmask + offset, 0, size); 2186315a1350SMichael S. Tsirkin memset(pdev->used + offset, 0, QEMU_ALIGN_UP(size, 4)); 2187315a1350SMichael S. Tsirkin 2188315a1350SMichael S. Tsirkin if (!pdev->config[PCI_CAPABILITY_LIST]) 2189315a1350SMichael S. Tsirkin pdev->config[PCI_STATUS] &= ~PCI_STATUS_CAP_LIST; 2190315a1350SMichael S. Tsirkin } 2191315a1350SMichael S. Tsirkin 2192315a1350SMichael S. Tsirkin uint8_t pci_find_capability(PCIDevice *pdev, uint8_t cap_id) 2193315a1350SMichael S. Tsirkin { 2194315a1350SMichael S. Tsirkin return pci_find_capability_list(pdev, cap_id, NULL); 2195315a1350SMichael S. Tsirkin } 2196315a1350SMichael S. Tsirkin 2197315a1350SMichael S. Tsirkin static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent) 2198315a1350SMichael S. Tsirkin { 2199315a1350SMichael S. Tsirkin PCIDevice *d = (PCIDevice *)dev; 2200315a1350SMichael S. Tsirkin const pci_class_desc *desc; 2201315a1350SMichael S. Tsirkin char ctxt[64]; 2202315a1350SMichael S. Tsirkin PCIIORegion *r; 2203315a1350SMichael S. Tsirkin int i, class; 2204315a1350SMichael S. Tsirkin 2205315a1350SMichael S. Tsirkin class = pci_get_word(d->config + PCI_CLASS_DEVICE); 2206315a1350SMichael S. Tsirkin desc = pci_class_descriptions; 2207315a1350SMichael S. Tsirkin while (desc->desc && class != desc->class) 2208315a1350SMichael S. Tsirkin desc++; 2209315a1350SMichael S. Tsirkin if (desc->desc) { 2210315a1350SMichael S. Tsirkin snprintf(ctxt, sizeof(ctxt), "%s", desc->desc); 2211315a1350SMichael S. Tsirkin } else { 2212315a1350SMichael S. Tsirkin snprintf(ctxt, sizeof(ctxt), "Class %04x", class); 2213315a1350SMichael S. Tsirkin } 2214315a1350SMichael S. Tsirkin 2215315a1350SMichael S. Tsirkin monitor_printf(mon, "%*sclass %s, addr %02x:%02x.%x, " 2216315a1350SMichael S. Tsirkin "pci id %04x:%04x (sub %04x:%04x)\n", 2217315a1350SMichael S. Tsirkin indent, "", ctxt, pci_bus_num(d->bus), 2218315a1350SMichael S. Tsirkin PCI_SLOT(d->devfn), PCI_FUNC(d->devfn), 2219315a1350SMichael S. Tsirkin pci_get_word(d->config + PCI_VENDOR_ID), 2220315a1350SMichael S. Tsirkin pci_get_word(d->config + PCI_DEVICE_ID), 2221315a1350SMichael S. Tsirkin pci_get_word(d->config + PCI_SUBSYSTEM_VENDOR_ID), 2222315a1350SMichael S. Tsirkin pci_get_word(d->config + PCI_SUBSYSTEM_ID)); 2223315a1350SMichael S. Tsirkin for (i = 0; i < PCI_NUM_REGIONS; i++) { 2224315a1350SMichael S. Tsirkin r = &d->io_regions[i]; 2225315a1350SMichael S. Tsirkin if (!r->size) 2226315a1350SMichael S. Tsirkin continue; 2227315a1350SMichael S. Tsirkin monitor_printf(mon, "%*sbar %d: %s at 0x%"FMT_PCIBUS 2228315a1350SMichael S. Tsirkin " [0x%"FMT_PCIBUS"]\n", 2229315a1350SMichael S. Tsirkin indent, "", 2230315a1350SMichael S. Tsirkin i, r->type & PCI_BASE_ADDRESS_SPACE_IO ? "i/o" : "mem", 2231315a1350SMichael S. Tsirkin r->addr, r->addr + r->size - 1); 2232315a1350SMichael S. Tsirkin } 2233315a1350SMichael S. Tsirkin } 2234315a1350SMichael S. Tsirkin 2235315a1350SMichael S. Tsirkin static char *pci_dev_fw_name(DeviceState *dev, char *buf, int len) 2236315a1350SMichael S. Tsirkin { 2237315a1350SMichael S. Tsirkin PCIDevice *d = (PCIDevice *)dev; 2238315a1350SMichael S. Tsirkin const char *name = NULL; 2239315a1350SMichael S. Tsirkin const pci_class_desc *desc = pci_class_descriptions; 2240315a1350SMichael S. Tsirkin int class = pci_get_word(d->config + PCI_CLASS_DEVICE); 2241315a1350SMichael S. Tsirkin 2242315a1350SMichael S. Tsirkin while (desc->desc && 2243315a1350SMichael S. Tsirkin (class & ~desc->fw_ign_bits) != 2244315a1350SMichael S. Tsirkin (desc->class & ~desc->fw_ign_bits)) { 2245315a1350SMichael S. Tsirkin desc++; 2246315a1350SMichael S. Tsirkin } 2247315a1350SMichael S. Tsirkin 2248315a1350SMichael S. Tsirkin if (desc->desc) { 2249315a1350SMichael S. Tsirkin name = desc->fw_name; 2250315a1350SMichael S. Tsirkin } 2251315a1350SMichael S. Tsirkin 2252315a1350SMichael S. Tsirkin if (name) { 2253315a1350SMichael S. Tsirkin pstrcpy(buf, len, name); 2254315a1350SMichael S. Tsirkin } else { 2255315a1350SMichael S. Tsirkin snprintf(buf, len, "pci%04x,%04x", 2256315a1350SMichael S. Tsirkin pci_get_word(d->config + PCI_VENDOR_ID), 2257315a1350SMichael S. Tsirkin pci_get_word(d->config + PCI_DEVICE_ID)); 2258315a1350SMichael S. Tsirkin } 2259315a1350SMichael S. Tsirkin 2260315a1350SMichael S. Tsirkin return buf; 2261315a1350SMichael S. Tsirkin } 2262315a1350SMichael S. Tsirkin 2263315a1350SMichael S. Tsirkin static char *pcibus_get_fw_dev_path(DeviceState *dev) 2264315a1350SMichael S. Tsirkin { 2265315a1350SMichael S. Tsirkin PCIDevice *d = (PCIDevice *)dev; 2266315a1350SMichael S. Tsirkin char path[50], name[33]; 2267315a1350SMichael S. Tsirkin int off; 2268315a1350SMichael S. Tsirkin 2269315a1350SMichael S. Tsirkin off = snprintf(path, sizeof(path), "%s@%x", 2270315a1350SMichael S. Tsirkin pci_dev_fw_name(dev, name, sizeof name), 2271315a1350SMichael S. Tsirkin PCI_SLOT(d->devfn)); 2272315a1350SMichael S. Tsirkin if (PCI_FUNC(d->devfn)) 2273315a1350SMichael S. Tsirkin snprintf(path + off, sizeof(path) + off, ",%x", PCI_FUNC(d->devfn)); 2274315a1350SMichael S. Tsirkin return g_strdup(path); 2275315a1350SMichael S. Tsirkin } 2276315a1350SMichael S. Tsirkin 2277315a1350SMichael S. Tsirkin static char *pcibus_get_dev_path(DeviceState *dev) 2278315a1350SMichael S. Tsirkin { 2279315a1350SMichael S. Tsirkin PCIDevice *d = container_of(dev, PCIDevice, qdev); 2280315a1350SMichael S. Tsirkin PCIDevice *t; 2281315a1350SMichael S. Tsirkin int slot_depth; 2282315a1350SMichael S. Tsirkin /* Path format: Domain:00:Slot.Function:Slot.Function....:Slot.Function. 2283315a1350SMichael S. Tsirkin * 00 is added here to make this format compatible with 2284315a1350SMichael S. Tsirkin * domain:Bus:Slot.Func for systems without nested PCI bridges. 2285315a1350SMichael S. Tsirkin * Slot.Function list specifies the slot and function numbers for all 2286315a1350SMichael S. Tsirkin * devices on the path from root to the specific device. */ 2287568f0690SDavid Gibson const char *root_bus_path; 2288568f0690SDavid Gibson int root_bus_len; 2289315a1350SMichael S. Tsirkin char slot[] = ":SS.F"; 2290315a1350SMichael S. Tsirkin int slot_len = sizeof slot - 1 /* For '\0' */; 2291315a1350SMichael S. Tsirkin int path_len; 2292315a1350SMichael S. Tsirkin char *path, *p; 2293315a1350SMichael S. Tsirkin int s; 2294315a1350SMichael S. Tsirkin 2295568f0690SDavid Gibson root_bus_path = pci_root_bus_path(d); 2296568f0690SDavid Gibson root_bus_len = strlen(root_bus_path); 2297568f0690SDavid Gibson 2298315a1350SMichael S. Tsirkin /* Calculate # of slots on path between device and root. */; 2299315a1350SMichael S. Tsirkin slot_depth = 0; 2300315a1350SMichael S. Tsirkin for (t = d; t; t = t->bus->parent_dev) { 2301315a1350SMichael S. Tsirkin ++slot_depth; 2302315a1350SMichael S. Tsirkin } 2303315a1350SMichael S. Tsirkin 2304568f0690SDavid Gibson path_len = root_bus_len + slot_len * slot_depth; 2305315a1350SMichael S. Tsirkin 2306315a1350SMichael S. Tsirkin /* Allocate memory, fill in the terminating null byte. */ 2307315a1350SMichael S. Tsirkin path = g_malloc(path_len + 1 /* For '\0' */); 2308315a1350SMichael S. Tsirkin path[path_len] = '\0'; 2309315a1350SMichael S. Tsirkin 2310568f0690SDavid Gibson memcpy(path, root_bus_path, root_bus_len); 2311315a1350SMichael S. Tsirkin 2312315a1350SMichael S. Tsirkin /* Fill in slot numbers. We walk up from device to root, so need to print 2313315a1350SMichael S. Tsirkin * them in the reverse order, last to first. */ 2314315a1350SMichael S. Tsirkin p = path + path_len; 2315315a1350SMichael S. Tsirkin for (t = d; t; t = t->bus->parent_dev) { 2316315a1350SMichael S. Tsirkin p -= slot_len; 2317315a1350SMichael S. Tsirkin s = snprintf(slot, sizeof slot, ":%02x.%x", 2318315a1350SMichael S. Tsirkin PCI_SLOT(t->devfn), PCI_FUNC(t->devfn)); 2319315a1350SMichael S. Tsirkin assert(s == slot_len); 2320315a1350SMichael S. Tsirkin memcpy(p, slot, slot_len); 2321315a1350SMichael S. Tsirkin } 2322315a1350SMichael S. Tsirkin 2323315a1350SMichael S. Tsirkin return path; 2324315a1350SMichael S. Tsirkin } 2325315a1350SMichael S. Tsirkin 2326315a1350SMichael S. Tsirkin static int pci_qdev_find_recursive(PCIBus *bus, 2327315a1350SMichael S. Tsirkin const char *id, PCIDevice **pdev) 2328315a1350SMichael S. Tsirkin { 2329315a1350SMichael S. Tsirkin DeviceState *qdev = qdev_find_recursive(&bus->qbus, id); 2330315a1350SMichael S. Tsirkin if (!qdev) { 2331315a1350SMichael S. Tsirkin return -ENODEV; 2332315a1350SMichael S. Tsirkin } 2333315a1350SMichael S. Tsirkin 2334315a1350SMichael S. Tsirkin /* roughly check if given qdev is pci device */ 2335315a1350SMichael S. Tsirkin if (object_dynamic_cast(OBJECT(qdev), TYPE_PCI_DEVICE)) { 2336315a1350SMichael S. Tsirkin *pdev = PCI_DEVICE(qdev); 2337315a1350SMichael S. Tsirkin return 0; 2338315a1350SMichael S. Tsirkin } 2339315a1350SMichael S. Tsirkin return -EINVAL; 2340315a1350SMichael S. Tsirkin } 2341315a1350SMichael S. Tsirkin 2342315a1350SMichael S. Tsirkin int pci_qdev_find_device(const char *id, PCIDevice **pdev) 2343315a1350SMichael S. Tsirkin { 23447588e2b0SDavid Gibson PCIHostState *host_bridge; 2345315a1350SMichael S. Tsirkin int rc = -ENODEV; 2346315a1350SMichael S. Tsirkin 23477588e2b0SDavid Gibson QLIST_FOREACH(host_bridge, &pci_host_bridges, next) { 23487588e2b0SDavid Gibson int tmp = pci_qdev_find_recursive(host_bridge->bus, id, pdev); 2349315a1350SMichael S. Tsirkin if (!tmp) { 2350315a1350SMichael S. Tsirkin rc = 0; 2351315a1350SMichael S. Tsirkin break; 2352315a1350SMichael S. Tsirkin } 2353315a1350SMichael S. Tsirkin if (tmp != -ENODEV) { 2354315a1350SMichael S. Tsirkin rc = tmp; 2355315a1350SMichael S. Tsirkin } 2356315a1350SMichael S. Tsirkin } 2357315a1350SMichael S. Tsirkin 2358315a1350SMichael S. Tsirkin return rc; 2359315a1350SMichael S. Tsirkin } 2360315a1350SMichael S. Tsirkin 2361315a1350SMichael S. Tsirkin MemoryRegion *pci_address_space(PCIDevice *dev) 2362315a1350SMichael S. Tsirkin { 2363315a1350SMichael S. Tsirkin return dev->bus->address_space_mem; 2364315a1350SMichael S. Tsirkin } 2365315a1350SMichael S. Tsirkin 2366315a1350SMichael S. Tsirkin MemoryRegion *pci_address_space_io(PCIDevice *dev) 2367315a1350SMichael S. Tsirkin { 2368315a1350SMichael S. Tsirkin return dev->bus->address_space_io; 2369315a1350SMichael S. Tsirkin } 2370315a1350SMichael S. Tsirkin 2371315a1350SMichael S. Tsirkin static void pci_device_class_init(ObjectClass *klass, void *data) 2372315a1350SMichael S. Tsirkin { 2373315a1350SMichael S. Tsirkin DeviceClass *k = DEVICE_CLASS(klass); 23747ee6c1e1SMarkus Armbruster PCIDeviceClass *pc = PCI_DEVICE_CLASS(klass); 23757ee6c1e1SMarkus Armbruster 2376133e9b22SMarkus Armbruster k->realize = pci_qdev_realize; 2377133e9b22SMarkus Armbruster k->unrealize = pci_qdev_unrealize; 2378315a1350SMichael S. Tsirkin k->bus_type = TYPE_PCI_BUS; 2379315a1350SMichael S. Tsirkin k->props = pci_props; 23807ee6c1e1SMarkus Armbruster pc->realize = pci_default_realize; 2381315a1350SMichael S. Tsirkin } 2382315a1350SMichael S. Tsirkin 23839eda7d37SAlexey Kardashevskiy AddressSpace *pci_device_iommu_address_space(PCIDevice *dev) 23849eda7d37SAlexey Kardashevskiy { 23859eda7d37SAlexey Kardashevskiy PCIBus *bus = PCI_BUS(dev->bus); 23869eda7d37SAlexey Kardashevskiy 23879eda7d37SAlexey Kardashevskiy if (bus->iommu_fn) { 23889eda7d37SAlexey Kardashevskiy return bus->iommu_fn(bus, bus->iommu_opaque, dev->devfn); 23899eda7d37SAlexey Kardashevskiy } 23909eda7d37SAlexey Kardashevskiy 23919eda7d37SAlexey Kardashevskiy if (bus->parent_dev) { 23929eda7d37SAlexey Kardashevskiy /** We are ignoring the bus master DMA bit of the bridge 23939eda7d37SAlexey Kardashevskiy * as it would complicate things such as VFIO for no good reason */ 23949eda7d37SAlexey Kardashevskiy return pci_device_iommu_address_space(bus->parent_dev); 23959eda7d37SAlexey Kardashevskiy } 23969eda7d37SAlexey Kardashevskiy 23979eda7d37SAlexey Kardashevskiy return &address_space_memory; 23989eda7d37SAlexey Kardashevskiy } 23999eda7d37SAlexey Kardashevskiy 2400e00387d5SAvi Kivity void pci_setup_iommu(PCIBus *bus, PCIIOMMUFunc fn, void *opaque) 2401315a1350SMichael S. Tsirkin { 2402e00387d5SAvi Kivity bus->iommu_fn = fn; 2403e00387d5SAvi Kivity bus->iommu_opaque = opaque; 2404315a1350SMichael S. Tsirkin } 2405315a1350SMichael S. Tsirkin 240643864069SMichael S. Tsirkin static void pci_dev_get_w64(PCIBus *b, PCIDevice *dev, void *opaque) 240743864069SMichael S. Tsirkin { 240843864069SMichael S. Tsirkin Range *range = opaque; 240943864069SMichael S. Tsirkin PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev); 241043864069SMichael S. Tsirkin uint16_t cmd = pci_get_word(dev->config + PCI_COMMAND); 241177d6f4eaSMichael S. Tsirkin int i; 241243864069SMichael S. Tsirkin 241343864069SMichael S. Tsirkin if (!(cmd & PCI_COMMAND_MEMORY)) { 241443864069SMichael S. Tsirkin return; 241543864069SMichael S. Tsirkin } 241643864069SMichael S. Tsirkin 241743864069SMichael S. Tsirkin if (pc->is_bridge) { 241843864069SMichael S. Tsirkin pcibus_t base = pci_bridge_get_base(dev, PCI_BASE_ADDRESS_MEM_PREFETCH); 241943864069SMichael S. Tsirkin pcibus_t limit = pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_MEM_PREFETCH); 242043864069SMichael S. Tsirkin 242143864069SMichael S. Tsirkin base = MAX(base, 0x1ULL << 32); 242243864069SMichael S. Tsirkin 242343864069SMichael S. Tsirkin if (limit >= base) { 242443864069SMichael S. Tsirkin Range pref_range; 242543864069SMichael S. Tsirkin pref_range.begin = base; 242643864069SMichael S. Tsirkin pref_range.end = limit + 1; 242743864069SMichael S. Tsirkin range_extend(range, &pref_range); 242843864069SMichael S. Tsirkin } 242943864069SMichael S. Tsirkin } 243077d6f4eaSMichael S. Tsirkin for (i = 0; i < PCI_NUM_REGIONS; ++i) { 243177d6f4eaSMichael S. Tsirkin PCIIORegion *r = &dev->io_regions[i]; 243243864069SMichael S. Tsirkin Range region_range; 243343864069SMichael S. Tsirkin 243477d6f4eaSMichael S. Tsirkin if (!r->size || 243577d6f4eaSMichael S. Tsirkin (r->type & PCI_BASE_ADDRESS_SPACE_IO) || 243677d6f4eaSMichael S. Tsirkin !(r->type & PCI_BASE_ADDRESS_MEM_TYPE_64)) { 243743864069SMichael S. Tsirkin continue; 243843864069SMichael S. Tsirkin } 243977d6f4eaSMichael S. Tsirkin region_range.begin = pci_bar_address(dev, i, r->type, r->size); 244077d6f4eaSMichael S. Tsirkin region_range.end = region_range.begin + r->size; 244177d6f4eaSMichael S. Tsirkin 244277d6f4eaSMichael S. Tsirkin if (region_range.begin == PCI_BAR_UNMAPPED) { 244377d6f4eaSMichael S. Tsirkin continue; 244477d6f4eaSMichael S. Tsirkin } 244543864069SMichael S. Tsirkin 244643864069SMichael S. Tsirkin region_range.begin = MAX(region_range.begin, 0x1ULL << 32); 244743864069SMichael S. Tsirkin 244843864069SMichael S. Tsirkin if (region_range.end - 1 >= region_range.begin) { 244943864069SMichael S. Tsirkin range_extend(range, ®ion_range); 245043864069SMichael S. Tsirkin } 245143864069SMichael S. Tsirkin } 245243864069SMichael S. Tsirkin } 245343864069SMichael S. Tsirkin 245443864069SMichael S. Tsirkin void pci_bus_get_w64_range(PCIBus *bus, Range *range) 245543864069SMichael S. Tsirkin { 245643864069SMichael S. Tsirkin range->begin = range->end = 0; 245743864069SMichael S. Tsirkin pci_for_each_device_under_bus(bus, pci_dev_get_w64, range); 245843864069SMichael S. Tsirkin } 245943864069SMichael S. Tsirkin 24608c43a6f0SAndreas Färber static const TypeInfo pci_device_type_info = { 2461315a1350SMichael S. Tsirkin .name = TYPE_PCI_DEVICE, 2462315a1350SMichael S. Tsirkin .parent = TYPE_DEVICE, 2463315a1350SMichael S. Tsirkin .instance_size = sizeof(PCIDevice), 2464315a1350SMichael S. Tsirkin .abstract = true, 2465315a1350SMichael S. Tsirkin .class_size = sizeof(PCIDeviceClass), 2466315a1350SMichael S. Tsirkin .class_init = pci_device_class_init, 2467315a1350SMichael S. Tsirkin }; 2468315a1350SMichael S. Tsirkin 2469315a1350SMichael S. Tsirkin static void pci_register_types(void) 2470315a1350SMichael S. Tsirkin { 2471315a1350SMichael S. Tsirkin type_register_static(&pci_bus_info); 24723a861c46SAlex Williamson type_register_static(&pcie_bus_info); 2473315a1350SMichael S. Tsirkin type_register_static(&pci_device_type_info); 2474315a1350SMichael S. Tsirkin } 2475315a1350SMichael S. Tsirkin 2476315a1350SMichael S. Tsirkin type_init(pci_register_types) 2477