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" 28315a1350SMichael S. Tsirkin #include "monitor.h" 291422e32dSPaolo Bonzini #include "net/net.h" 30315a1350SMichael S. Tsirkin #include "sysemu.h" 31c759b24fSMichael S. Tsirkin #include "hw/loader.h" 32315a1350SMichael S. Tsirkin #include "range.h" 33315a1350SMichael S. Tsirkin #include "qmp-commands.h" 34c759b24fSMichael S. Tsirkin #include "hw/pci/msi.h" 35c759b24fSMichael S. Tsirkin #include "hw/pci/msix.h" 36*022c62cbSPaolo Bonzini #include "exec/address-spaces.h" 37315a1350SMichael S. Tsirkin 38315a1350SMichael S. Tsirkin //#define DEBUG_PCI 39315a1350SMichael S. Tsirkin #ifdef DEBUG_PCI 40315a1350SMichael S. Tsirkin # define PCI_DPRINTF(format, ...) printf(format, ## __VA_ARGS__) 41315a1350SMichael S. Tsirkin #else 42315a1350SMichael S. Tsirkin # define PCI_DPRINTF(format, ...) do { } while (0) 43315a1350SMichael S. Tsirkin #endif 44315a1350SMichael S. Tsirkin 45315a1350SMichael S. Tsirkin static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent); 46315a1350SMichael S. Tsirkin static char *pcibus_get_dev_path(DeviceState *dev); 47315a1350SMichael S. Tsirkin static char *pcibus_get_fw_dev_path(DeviceState *dev); 48315a1350SMichael S. Tsirkin static int pcibus_reset(BusState *qbus); 49315a1350SMichael S. Tsirkin 50315a1350SMichael S. Tsirkin static Property pci_props[] = { 51315a1350SMichael S. Tsirkin DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1), 52315a1350SMichael S. Tsirkin DEFINE_PROP_STRING("romfile", PCIDevice, romfile), 53315a1350SMichael S. Tsirkin DEFINE_PROP_UINT32("rombar", PCIDevice, rom_bar, 1), 54315a1350SMichael S. Tsirkin DEFINE_PROP_BIT("multifunction", PCIDevice, cap_present, 55315a1350SMichael S. Tsirkin QEMU_PCI_CAP_MULTIFUNCTION_BITNR, false), 56315a1350SMichael S. Tsirkin DEFINE_PROP_BIT("command_serr_enable", PCIDevice, cap_present, 57315a1350SMichael S. Tsirkin QEMU_PCI_CAP_SERR_BITNR, true), 58315a1350SMichael S. Tsirkin DEFINE_PROP_END_OF_LIST() 59315a1350SMichael S. Tsirkin }; 60315a1350SMichael S. Tsirkin 61315a1350SMichael S. Tsirkin static void pci_bus_class_init(ObjectClass *klass, void *data) 62315a1350SMichael S. Tsirkin { 63315a1350SMichael S. Tsirkin BusClass *k = BUS_CLASS(klass); 64315a1350SMichael S. Tsirkin 65315a1350SMichael S. Tsirkin k->print_dev = pcibus_dev_print; 66315a1350SMichael S. Tsirkin k->get_dev_path = pcibus_get_dev_path; 67315a1350SMichael S. Tsirkin k->get_fw_dev_path = pcibus_get_fw_dev_path; 68315a1350SMichael S. Tsirkin k->reset = pcibus_reset; 69315a1350SMichael S. Tsirkin } 70315a1350SMichael S. Tsirkin 71315a1350SMichael S. Tsirkin static const TypeInfo pci_bus_info = { 72315a1350SMichael S. Tsirkin .name = TYPE_PCI_BUS, 73315a1350SMichael S. Tsirkin .parent = TYPE_BUS, 74315a1350SMichael S. Tsirkin .instance_size = sizeof(PCIBus), 75315a1350SMichael S. Tsirkin .class_init = pci_bus_class_init, 76315a1350SMichael S. Tsirkin }; 77315a1350SMichael S. Tsirkin 78315a1350SMichael S. Tsirkin static PCIBus *pci_find_bus_nr(PCIBus *bus, int bus_num); 79315a1350SMichael S. Tsirkin static void pci_update_mappings(PCIDevice *d); 80315a1350SMichael S. Tsirkin static void pci_set_irq(void *opaque, int irq_num, int level); 81315a1350SMichael S. Tsirkin static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom); 82315a1350SMichael S. Tsirkin static void pci_del_option_rom(PCIDevice *pdev); 83315a1350SMichael S. Tsirkin 84315a1350SMichael S. Tsirkin static uint16_t pci_default_sub_vendor_id = PCI_SUBVENDOR_ID_REDHAT_QUMRANET; 85315a1350SMichael S. Tsirkin static uint16_t pci_default_sub_device_id = PCI_SUBDEVICE_ID_QEMU; 86315a1350SMichael S. Tsirkin 87315a1350SMichael S. Tsirkin struct PCIHostBus { 88315a1350SMichael S. Tsirkin int domain; 89315a1350SMichael S. Tsirkin struct PCIBus *bus; 90315a1350SMichael S. Tsirkin QLIST_ENTRY(PCIHostBus) next; 91315a1350SMichael S. Tsirkin }; 92315a1350SMichael S. Tsirkin static QLIST_HEAD(, PCIHostBus) host_buses; 93315a1350SMichael S. Tsirkin 94315a1350SMichael S. Tsirkin static const VMStateDescription vmstate_pcibus = { 95315a1350SMichael S. Tsirkin .name = "PCIBUS", 96315a1350SMichael S. Tsirkin .version_id = 1, 97315a1350SMichael S. Tsirkin .minimum_version_id = 1, 98315a1350SMichael S. Tsirkin .minimum_version_id_old = 1, 99315a1350SMichael S. Tsirkin .fields = (VMStateField []) { 100315a1350SMichael S. Tsirkin VMSTATE_INT32_EQUAL(nirq, PCIBus), 101315a1350SMichael S. Tsirkin VMSTATE_VARRAY_INT32(irq_count, PCIBus, nirq, 0, vmstate_info_int32, int32_t), 102315a1350SMichael S. Tsirkin VMSTATE_END_OF_LIST() 103315a1350SMichael S. Tsirkin } 104315a1350SMichael S. Tsirkin }; 105315a1350SMichael S. Tsirkin static int pci_bar(PCIDevice *d, int reg) 106315a1350SMichael S. Tsirkin { 107315a1350SMichael S. Tsirkin uint8_t type; 108315a1350SMichael S. Tsirkin 109315a1350SMichael S. Tsirkin if (reg != PCI_ROM_SLOT) 110315a1350SMichael S. Tsirkin return PCI_BASE_ADDRESS_0 + reg * 4; 111315a1350SMichael S. Tsirkin 112315a1350SMichael S. Tsirkin type = d->config[PCI_HEADER_TYPE] & ~PCI_HEADER_TYPE_MULTI_FUNCTION; 113315a1350SMichael S. Tsirkin return type == PCI_HEADER_TYPE_BRIDGE ? PCI_ROM_ADDRESS1 : PCI_ROM_ADDRESS; 114315a1350SMichael S. Tsirkin } 115315a1350SMichael S. Tsirkin 116315a1350SMichael S. Tsirkin static inline int pci_irq_state(PCIDevice *d, int irq_num) 117315a1350SMichael S. Tsirkin { 118315a1350SMichael S. Tsirkin return (d->irq_state >> irq_num) & 0x1; 119315a1350SMichael S. Tsirkin } 120315a1350SMichael S. Tsirkin 121315a1350SMichael S. Tsirkin static inline void pci_set_irq_state(PCIDevice *d, int irq_num, int level) 122315a1350SMichael S. Tsirkin { 123315a1350SMichael S. Tsirkin d->irq_state &= ~(0x1 << irq_num); 124315a1350SMichael S. Tsirkin d->irq_state |= level << irq_num; 125315a1350SMichael S. Tsirkin } 126315a1350SMichael S. Tsirkin 127315a1350SMichael S. Tsirkin static void pci_change_irq_level(PCIDevice *pci_dev, int irq_num, int change) 128315a1350SMichael S. Tsirkin { 129315a1350SMichael S. Tsirkin PCIBus *bus; 130315a1350SMichael S. Tsirkin for (;;) { 131315a1350SMichael S. Tsirkin bus = pci_dev->bus; 132315a1350SMichael S. Tsirkin irq_num = bus->map_irq(pci_dev, irq_num); 133315a1350SMichael S. Tsirkin if (bus->set_irq) 134315a1350SMichael S. Tsirkin break; 135315a1350SMichael S. Tsirkin pci_dev = bus->parent_dev; 136315a1350SMichael S. Tsirkin } 137315a1350SMichael S. Tsirkin bus->irq_count[irq_num] += change; 138315a1350SMichael S. Tsirkin bus->set_irq(bus->irq_opaque, irq_num, bus->irq_count[irq_num] != 0); 139315a1350SMichael S. Tsirkin } 140315a1350SMichael S. Tsirkin 141315a1350SMichael S. Tsirkin int pci_bus_get_irq_level(PCIBus *bus, int irq_num) 142315a1350SMichael S. Tsirkin { 143315a1350SMichael S. Tsirkin assert(irq_num >= 0); 144315a1350SMichael S. Tsirkin assert(irq_num < bus->nirq); 145315a1350SMichael S. Tsirkin return !!bus->irq_count[irq_num]; 146315a1350SMichael S. Tsirkin } 147315a1350SMichael S. Tsirkin 148315a1350SMichael S. Tsirkin /* Update interrupt status bit in config space on interrupt 149315a1350SMichael S. Tsirkin * state change. */ 150315a1350SMichael S. Tsirkin static void pci_update_irq_status(PCIDevice *dev) 151315a1350SMichael S. Tsirkin { 152315a1350SMichael S. Tsirkin if (dev->irq_state) { 153315a1350SMichael S. Tsirkin dev->config[PCI_STATUS] |= PCI_STATUS_INTERRUPT; 154315a1350SMichael S. Tsirkin } else { 155315a1350SMichael S. Tsirkin dev->config[PCI_STATUS] &= ~PCI_STATUS_INTERRUPT; 156315a1350SMichael S. Tsirkin } 157315a1350SMichael S. Tsirkin } 158315a1350SMichael S. Tsirkin 159315a1350SMichael S. Tsirkin void pci_device_deassert_intx(PCIDevice *dev) 160315a1350SMichael S. Tsirkin { 161315a1350SMichael S. Tsirkin int i; 162315a1350SMichael S. Tsirkin for (i = 0; i < PCI_NUM_PINS; ++i) { 163315a1350SMichael S. Tsirkin qemu_set_irq(dev->irq[i], 0); 164315a1350SMichael S. Tsirkin } 165315a1350SMichael S. Tsirkin } 166315a1350SMichael S. Tsirkin 167315a1350SMichael S. Tsirkin /* 168315a1350SMichael S. Tsirkin * This function is called on #RST and FLR. 169315a1350SMichael S. Tsirkin * FLR if PCI_EXP_DEVCTL_BCR_FLR is set 170315a1350SMichael S. Tsirkin */ 171315a1350SMichael S. Tsirkin void pci_device_reset(PCIDevice *dev) 172315a1350SMichael S. Tsirkin { 173315a1350SMichael S. Tsirkin int r; 174315a1350SMichael S. Tsirkin 175315a1350SMichael S. Tsirkin qdev_reset_all(&dev->qdev); 176315a1350SMichael S. Tsirkin 177315a1350SMichael S. Tsirkin dev->irq_state = 0; 178315a1350SMichael S. Tsirkin pci_update_irq_status(dev); 179315a1350SMichael S. Tsirkin pci_device_deassert_intx(dev); 180315a1350SMichael S. Tsirkin /* Clear all writable bits */ 181315a1350SMichael S. Tsirkin pci_word_test_and_clear_mask(dev->config + PCI_COMMAND, 182315a1350SMichael S. Tsirkin pci_get_word(dev->wmask + PCI_COMMAND) | 183315a1350SMichael S. Tsirkin pci_get_word(dev->w1cmask + PCI_COMMAND)); 184315a1350SMichael S. Tsirkin pci_word_test_and_clear_mask(dev->config + PCI_STATUS, 185315a1350SMichael S. Tsirkin pci_get_word(dev->wmask + PCI_STATUS) | 186315a1350SMichael S. Tsirkin pci_get_word(dev->w1cmask + PCI_STATUS)); 187315a1350SMichael S. Tsirkin dev->config[PCI_CACHE_LINE_SIZE] = 0x0; 188315a1350SMichael S. Tsirkin dev->config[PCI_INTERRUPT_LINE] = 0x0; 189315a1350SMichael S. Tsirkin for (r = 0; r < PCI_NUM_REGIONS; ++r) { 190315a1350SMichael S. Tsirkin PCIIORegion *region = &dev->io_regions[r]; 191315a1350SMichael S. Tsirkin if (!region->size) { 192315a1350SMichael S. Tsirkin continue; 193315a1350SMichael S. Tsirkin } 194315a1350SMichael S. Tsirkin 195315a1350SMichael S. Tsirkin if (!(region->type & PCI_BASE_ADDRESS_SPACE_IO) && 196315a1350SMichael S. Tsirkin region->type & PCI_BASE_ADDRESS_MEM_TYPE_64) { 197315a1350SMichael S. Tsirkin pci_set_quad(dev->config + pci_bar(dev, r), region->type); 198315a1350SMichael S. Tsirkin } else { 199315a1350SMichael S. Tsirkin pci_set_long(dev->config + pci_bar(dev, r), region->type); 200315a1350SMichael S. Tsirkin } 201315a1350SMichael S. Tsirkin } 202315a1350SMichael S. Tsirkin pci_update_mappings(dev); 203315a1350SMichael S. Tsirkin 204315a1350SMichael S. Tsirkin msi_reset(dev); 205315a1350SMichael S. Tsirkin msix_reset(dev); 206315a1350SMichael S. Tsirkin } 207315a1350SMichael S. Tsirkin 208315a1350SMichael S. Tsirkin /* 209315a1350SMichael S. Tsirkin * Trigger pci bus reset under a given bus. 210315a1350SMichael S. Tsirkin * To be called on RST# assert. 211315a1350SMichael S. Tsirkin */ 212315a1350SMichael S. Tsirkin void pci_bus_reset(PCIBus *bus) 213315a1350SMichael S. Tsirkin { 214315a1350SMichael S. Tsirkin int i; 215315a1350SMichael S. Tsirkin 216315a1350SMichael S. Tsirkin for (i = 0; i < bus->nirq; i++) { 217315a1350SMichael S. Tsirkin bus->irq_count[i] = 0; 218315a1350SMichael S. Tsirkin } 219315a1350SMichael S. Tsirkin for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) { 220315a1350SMichael S. Tsirkin if (bus->devices[i]) { 221315a1350SMichael S. Tsirkin pci_device_reset(bus->devices[i]); 222315a1350SMichael S. Tsirkin } 223315a1350SMichael S. Tsirkin } 224315a1350SMichael S. Tsirkin } 225315a1350SMichael S. Tsirkin 226315a1350SMichael S. Tsirkin static int pcibus_reset(BusState *qbus) 227315a1350SMichael S. Tsirkin { 228315a1350SMichael S. Tsirkin pci_bus_reset(DO_UPCAST(PCIBus, qbus, qbus)); 229315a1350SMichael S. Tsirkin 230315a1350SMichael S. Tsirkin /* topology traverse is done by pci_bus_reset(). 231315a1350SMichael S. Tsirkin Tell qbus/qdev walker not to traverse the tree */ 232315a1350SMichael S. Tsirkin return 1; 233315a1350SMichael S. Tsirkin } 234315a1350SMichael S. Tsirkin 235315a1350SMichael S. Tsirkin static void pci_host_bus_register(int domain, PCIBus *bus) 236315a1350SMichael S. Tsirkin { 237315a1350SMichael S. Tsirkin struct PCIHostBus *host; 238315a1350SMichael S. Tsirkin host = g_malloc0(sizeof(*host)); 239315a1350SMichael S. Tsirkin host->domain = domain; 240315a1350SMichael S. Tsirkin host->bus = bus; 241315a1350SMichael S. Tsirkin QLIST_INSERT_HEAD(&host_buses, host, next); 242315a1350SMichael S. Tsirkin } 243315a1350SMichael S. Tsirkin 244315a1350SMichael S. Tsirkin PCIBus *pci_find_root_bus(int domain) 245315a1350SMichael S. Tsirkin { 246315a1350SMichael S. Tsirkin struct PCIHostBus *host; 247315a1350SMichael S. Tsirkin 248315a1350SMichael S. Tsirkin QLIST_FOREACH(host, &host_buses, next) { 249315a1350SMichael S. Tsirkin if (host->domain == domain) { 250315a1350SMichael S. Tsirkin return host->bus; 251315a1350SMichael S. Tsirkin } 252315a1350SMichael S. Tsirkin } 253315a1350SMichael S. Tsirkin 254315a1350SMichael S. Tsirkin return NULL; 255315a1350SMichael S. Tsirkin } 256315a1350SMichael S. Tsirkin 257315a1350SMichael S. Tsirkin int pci_find_domain(const PCIBus *bus) 258315a1350SMichael S. Tsirkin { 259315a1350SMichael S. Tsirkin PCIDevice *d; 260315a1350SMichael S. Tsirkin struct PCIHostBus *host; 261315a1350SMichael S. Tsirkin 262315a1350SMichael S. Tsirkin /* obtain root bus */ 263315a1350SMichael S. Tsirkin while ((d = bus->parent_dev) != NULL) { 264315a1350SMichael S. Tsirkin bus = d->bus; 265315a1350SMichael S. Tsirkin } 266315a1350SMichael S. Tsirkin 267315a1350SMichael S. Tsirkin QLIST_FOREACH(host, &host_buses, next) { 268315a1350SMichael S. Tsirkin if (host->bus == bus) { 269315a1350SMichael S. Tsirkin return host->domain; 270315a1350SMichael S. Tsirkin } 271315a1350SMichael S. Tsirkin } 272315a1350SMichael S. Tsirkin 273315a1350SMichael S. Tsirkin abort(); /* should not be reached */ 274315a1350SMichael S. Tsirkin return -1; 275315a1350SMichael S. Tsirkin } 276315a1350SMichael S. Tsirkin 277315a1350SMichael S. Tsirkin void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent, 278315a1350SMichael S. Tsirkin const char *name, 279315a1350SMichael S. Tsirkin MemoryRegion *address_space_mem, 280315a1350SMichael S. Tsirkin MemoryRegion *address_space_io, 281315a1350SMichael S. Tsirkin uint8_t devfn_min) 282315a1350SMichael S. Tsirkin { 283315a1350SMichael S. Tsirkin qbus_create_inplace(&bus->qbus, TYPE_PCI_BUS, parent, name); 284315a1350SMichael S. Tsirkin assert(PCI_FUNC(devfn_min) == 0); 285315a1350SMichael S. Tsirkin bus->devfn_min = devfn_min; 286315a1350SMichael S. Tsirkin bus->address_space_mem = address_space_mem; 287315a1350SMichael S. Tsirkin bus->address_space_io = address_space_io; 288315a1350SMichael S. Tsirkin 289315a1350SMichael S. Tsirkin /* host bridge */ 290315a1350SMichael S. Tsirkin QLIST_INIT(&bus->child); 291315a1350SMichael S. Tsirkin pci_host_bus_register(0, bus); /* for now only pci domain 0 is supported */ 292315a1350SMichael S. Tsirkin 293315a1350SMichael S. Tsirkin vmstate_register(NULL, -1, &vmstate_pcibus, bus); 294315a1350SMichael S. Tsirkin } 295315a1350SMichael S. Tsirkin 296315a1350SMichael S. Tsirkin PCIBus *pci_bus_new(DeviceState *parent, const char *name, 297315a1350SMichael S. Tsirkin MemoryRegion *address_space_mem, 298315a1350SMichael S. Tsirkin MemoryRegion *address_space_io, 299315a1350SMichael S. Tsirkin uint8_t devfn_min) 300315a1350SMichael S. Tsirkin { 301315a1350SMichael S. Tsirkin PCIBus *bus; 302315a1350SMichael S. Tsirkin 303315a1350SMichael S. Tsirkin bus = g_malloc0(sizeof(*bus)); 304315a1350SMichael S. Tsirkin pci_bus_new_inplace(bus, parent, name, address_space_mem, 305315a1350SMichael S. Tsirkin address_space_io, devfn_min); 306315a1350SMichael S. Tsirkin OBJECT(bus)->free = g_free; 307315a1350SMichael S. Tsirkin return bus; 308315a1350SMichael S. Tsirkin } 309315a1350SMichael S. Tsirkin 310315a1350SMichael S. Tsirkin void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, 311315a1350SMichael S. Tsirkin void *irq_opaque, int nirq) 312315a1350SMichael S. Tsirkin { 313315a1350SMichael S. Tsirkin bus->set_irq = set_irq; 314315a1350SMichael S. Tsirkin bus->map_irq = map_irq; 315315a1350SMichael S. Tsirkin bus->irq_opaque = irq_opaque; 316315a1350SMichael S. Tsirkin bus->nirq = nirq; 317315a1350SMichael S. Tsirkin bus->irq_count = g_malloc0(nirq * sizeof(bus->irq_count[0])); 318315a1350SMichael S. Tsirkin } 319315a1350SMichael S. Tsirkin 320315a1350SMichael S. Tsirkin void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *qdev) 321315a1350SMichael S. Tsirkin { 322315a1350SMichael S. Tsirkin bus->qbus.allow_hotplug = 1; 323315a1350SMichael S. Tsirkin bus->hotplug = hotplug; 324315a1350SMichael S. Tsirkin bus->hotplug_qdev = qdev; 325315a1350SMichael S. Tsirkin } 326315a1350SMichael S. Tsirkin 327315a1350SMichael S. Tsirkin PCIBus *pci_register_bus(DeviceState *parent, const char *name, 328315a1350SMichael S. Tsirkin pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, 329315a1350SMichael S. Tsirkin void *irq_opaque, 330315a1350SMichael S. Tsirkin MemoryRegion *address_space_mem, 331315a1350SMichael S. Tsirkin MemoryRegion *address_space_io, 332315a1350SMichael S. Tsirkin uint8_t devfn_min, int nirq) 333315a1350SMichael S. Tsirkin { 334315a1350SMichael S. Tsirkin PCIBus *bus; 335315a1350SMichael S. Tsirkin 336315a1350SMichael S. Tsirkin bus = pci_bus_new(parent, name, address_space_mem, 337315a1350SMichael S. Tsirkin address_space_io, devfn_min); 338315a1350SMichael S. Tsirkin pci_bus_irqs(bus, set_irq, map_irq, irq_opaque, nirq); 339315a1350SMichael S. Tsirkin return bus; 340315a1350SMichael S. Tsirkin } 341315a1350SMichael S. Tsirkin 342315a1350SMichael S. Tsirkin int pci_bus_num(PCIBus *s) 343315a1350SMichael S. Tsirkin { 344315a1350SMichael S. Tsirkin if (!s->parent_dev) 345315a1350SMichael S. Tsirkin return 0; /* pci host bridge */ 346315a1350SMichael S. Tsirkin return s->parent_dev->config[PCI_SECONDARY_BUS]; 347315a1350SMichael S. Tsirkin } 348315a1350SMichael S. Tsirkin 349315a1350SMichael S. Tsirkin static int get_pci_config_device(QEMUFile *f, void *pv, size_t size) 350315a1350SMichael S. Tsirkin { 351315a1350SMichael S. Tsirkin PCIDevice *s = container_of(pv, PCIDevice, config); 352315a1350SMichael S. Tsirkin uint8_t *config; 353315a1350SMichael S. Tsirkin int i; 354315a1350SMichael S. Tsirkin 355315a1350SMichael S. Tsirkin assert(size == pci_config_size(s)); 356315a1350SMichael S. Tsirkin config = g_malloc(size); 357315a1350SMichael S. Tsirkin 358315a1350SMichael S. Tsirkin qemu_get_buffer(f, config, size); 359315a1350SMichael S. Tsirkin for (i = 0; i < size; ++i) { 360315a1350SMichael S. Tsirkin if ((config[i] ^ s->config[i]) & 361315a1350SMichael S. Tsirkin s->cmask[i] & ~s->wmask[i] & ~s->w1cmask[i]) { 362315a1350SMichael S. Tsirkin g_free(config); 363315a1350SMichael S. Tsirkin return -EINVAL; 364315a1350SMichael S. Tsirkin } 365315a1350SMichael S. Tsirkin } 366315a1350SMichael S. Tsirkin memcpy(s->config, config, size); 367315a1350SMichael S. Tsirkin 368315a1350SMichael S. Tsirkin pci_update_mappings(s); 369315a1350SMichael S. Tsirkin 370315a1350SMichael S. Tsirkin memory_region_set_enabled(&s->bus_master_enable_region, 371315a1350SMichael S. Tsirkin pci_get_word(s->config + PCI_COMMAND) 372315a1350SMichael S. Tsirkin & PCI_COMMAND_MASTER); 373315a1350SMichael S. Tsirkin 374315a1350SMichael S. Tsirkin g_free(config); 375315a1350SMichael S. Tsirkin return 0; 376315a1350SMichael S. Tsirkin } 377315a1350SMichael S. Tsirkin 378315a1350SMichael S. Tsirkin /* just put buffer */ 379315a1350SMichael S. Tsirkin static void put_pci_config_device(QEMUFile *f, void *pv, size_t size) 380315a1350SMichael S. Tsirkin { 381315a1350SMichael S. Tsirkin const uint8_t **v = pv; 382315a1350SMichael S. Tsirkin assert(size == pci_config_size(container_of(pv, PCIDevice, config))); 383315a1350SMichael S. Tsirkin qemu_put_buffer(f, *v, size); 384315a1350SMichael S. Tsirkin } 385315a1350SMichael S. Tsirkin 386315a1350SMichael S. Tsirkin static VMStateInfo vmstate_info_pci_config = { 387315a1350SMichael S. Tsirkin .name = "pci config", 388315a1350SMichael S. Tsirkin .get = get_pci_config_device, 389315a1350SMichael S. Tsirkin .put = put_pci_config_device, 390315a1350SMichael S. Tsirkin }; 391315a1350SMichael S. Tsirkin 392315a1350SMichael S. Tsirkin static int get_pci_irq_state(QEMUFile *f, void *pv, size_t size) 393315a1350SMichael S. Tsirkin { 394315a1350SMichael S. Tsirkin PCIDevice *s = container_of(pv, PCIDevice, irq_state); 395315a1350SMichael S. Tsirkin uint32_t irq_state[PCI_NUM_PINS]; 396315a1350SMichael S. Tsirkin int i; 397315a1350SMichael S. Tsirkin for (i = 0; i < PCI_NUM_PINS; ++i) { 398315a1350SMichael S. Tsirkin irq_state[i] = qemu_get_be32(f); 399315a1350SMichael S. Tsirkin if (irq_state[i] != 0x1 && irq_state[i] != 0) { 400315a1350SMichael S. Tsirkin fprintf(stderr, "irq state %d: must be 0 or 1.\n", 401315a1350SMichael S. Tsirkin irq_state[i]); 402315a1350SMichael S. Tsirkin return -EINVAL; 403315a1350SMichael S. Tsirkin } 404315a1350SMichael S. Tsirkin } 405315a1350SMichael S. Tsirkin 406315a1350SMichael S. Tsirkin for (i = 0; i < PCI_NUM_PINS; ++i) { 407315a1350SMichael S. Tsirkin pci_set_irq_state(s, i, irq_state[i]); 408315a1350SMichael S. Tsirkin } 409315a1350SMichael S. Tsirkin 410315a1350SMichael S. Tsirkin return 0; 411315a1350SMichael S. Tsirkin } 412315a1350SMichael S. Tsirkin 413315a1350SMichael S. Tsirkin static void put_pci_irq_state(QEMUFile *f, void *pv, size_t size) 414315a1350SMichael S. Tsirkin { 415315a1350SMichael S. Tsirkin int i; 416315a1350SMichael S. Tsirkin PCIDevice *s = container_of(pv, PCIDevice, irq_state); 417315a1350SMichael S. Tsirkin 418315a1350SMichael S. Tsirkin for (i = 0; i < PCI_NUM_PINS; ++i) { 419315a1350SMichael S. Tsirkin qemu_put_be32(f, pci_irq_state(s, i)); 420315a1350SMichael S. Tsirkin } 421315a1350SMichael S. Tsirkin } 422315a1350SMichael S. Tsirkin 423315a1350SMichael S. Tsirkin static VMStateInfo vmstate_info_pci_irq_state = { 424315a1350SMichael S. Tsirkin .name = "pci irq state", 425315a1350SMichael S. Tsirkin .get = get_pci_irq_state, 426315a1350SMichael S. Tsirkin .put = put_pci_irq_state, 427315a1350SMichael S. Tsirkin }; 428315a1350SMichael S. Tsirkin 429315a1350SMichael S. Tsirkin const VMStateDescription vmstate_pci_device = { 430315a1350SMichael S. Tsirkin .name = "PCIDevice", 431315a1350SMichael S. Tsirkin .version_id = 2, 432315a1350SMichael S. Tsirkin .minimum_version_id = 1, 433315a1350SMichael S. Tsirkin .minimum_version_id_old = 1, 434315a1350SMichael S. Tsirkin .fields = (VMStateField []) { 435315a1350SMichael S. Tsirkin VMSTATE_INT32_LE(version_id, PCIDevice), 436315a1350SMichael S. Tsirkin VMSTATE_BUFFER_UNSAFE_INFO(config, PCIDevice, 0, 437315a1350SMichael S. Tsirkin vmstate_info_pci_config, 438315a1350SMichael S. Tsirkin PCI_CONFIG_SPACE_SIZE), 439315a1350SMichael S. Tsirkin VMSTATE_BUFFER_UNSAFE_INFO(irq_state, PCIDevice, 2, 440315a1350SMichael S. Tsirkin vmstate_info_pci_irq_state, 441315a1350SMichael S. Tsirkin PCI_NUM_PINS * sizeof(int32_t)), 442315a1350SMichael S. Tsirkin VMSTATE_END_OF_LIST() 443315a1350SMichael S. Tsirkin } 444315a1350SMichael S. Tsirkin }; 445315a1350SMichael S. Tsirkin 446315a1350SMichael S. Tsirkin const VMStateDescription vmstate_pcie_device = { 447315a1350SMichael S. Tsirkin .name = "PCIEDevice", 448315a1350SMichael S. Tsirkin .version_id = 2, 449315a1350SMichael S. Tsirkin .minimum_version_id = 1, 450315a1350SMichael S. Tsirkin .minimum_version_id_old = 1, 451315a1350SMichael S. Tsirkin .fields = (VMStateField []) { 452315a1350SMichael S. Tsirkin VMSTATE_INT32_LE(version_id, PCIDevice), 453315a1350SMichael S. Tsirkin VMSTATE_BUFFER_UNSAFE_INFO(config, PCIDevice, 0, 454315a1350SMichael S. Tsirkin vmstate_info_pci_config, 455315a1350SMichael S. Tsirkin PCIE_CONFIG_SPACE_SIZE), 456315a1350SMichael S. Tsirkin VMSTATE_BUFFER_UNSAFE_INFO(irq_state, PCIDevice, 2, 457315a1350SMichael S. Tsirkin vmstate_info_pci_irq_state, 458315a1350SMichael S. Tsirkin PCI_NUM_PINS * sizeof(int32_t)), 459315a1350SMichael S. Tsirkin VMSTATE_END_OF_LIST() 460315a1350SMichael S. Tsirkin } 461315a1350SMichael S. Tsirkin }; 462315a1350SMichael S. Tsirkin 463315a1350SMichael S. Tsirkin static inline const VMStateDescription *pci_get_vmstate(PCIDevice *s) 464315a1350SMichael S. Tsirkin { 465315a1350SMichael S. Tsirkin return pci_is_express(s) ? &vmstate_pcie_device : &vmstate_pci_device; 466315a1350SMichael S. Tsirkin } 467315a1350SMichael S. Tsirkin 468315a1350SMichael S. Tsirkin void pci_device_save(PCIDevice *s, QEMUFile *f) 469315a1350SMichael S. Tsirkin { 470315a1350SMichael S. Tsirkin /* Clear interrupt status bit: it is implicit 471315a1350SMichael S. Tsirkin * in irq_state which we are saving. 472315a1350SMichael S. Tsirkin * This makes us compatible with old devices 473315a1350SMichael S. Tsirkin * which never set or clear this bit. */ 474315a1350SMichael S. Tsirkin s->config[PCI_STATUS] &= ~PCI_STATUS_INTERRUPT; 475315a1350SMichael S. Tsirkin vmstate_save_state(f, pci_get_vmstate(s), s); 476315a1350SMichael S. Tsirkin /* Restore the interrupt status bit. */ 477315a1350SMichael S. Tsirkin pci_update_irq_status(s); 478315a1350SMichael S. Tsirkin } 479315a1350SMichael S. Tsirkin 480315a1350SMichael S. Tsirkin int pci_device_load(PCIDevice *s, QEMUFile *f) 481315a1350SMichael S. Tsirkin { 482315a1350SMichael S. Tsirkin int ret; 483315a1350SMichael S. Tsirkin ret = vmstate_load_state(f, pci_get_vmstate(s), s, s->version_id); 484315a1350SMichael S. Tsirkin /* Restore the interrupt status bit. */ 485315a1350SMichael S. Tsirkin pci_update_irq_status(s); 486315a1350SMichael S. Tsirkin return ret; 487315a1350SMichael S. Tsirkin } 488315a1350SMichael S. Tsirkin 489315a1350SMichael S. Tsirkin static void pci_set_default_subsystem_id(PCIDevice *pci_dev) 490315a1350SMichael S. Tsirkin { 491315a1350SMichael S. Tsirkin pci_set_word(pci_dev->config + PCI_SUBSYSTEM_VENDOR_ID, 492315a1350SMichael S. Tsirkin pci_default_sub_vendor_id); 493315a1350SMichael S. Tsirkin pci_set_word(pci_dev->config + PCI_SUBSYSTEM_ID, 494315a1350SMichael S. Tsirkin pci_default_sub_device_id); 495315a1350SMichael S. Tsirkin } 496315a1350SMichael S. Tsirkin 497315a1350SMichael S. Tsirkin /* 498315a1350SMichael S. Tsirkin * Parse [[<domain>:]<bus>:]<slot>, return -1 on error if funcp == NULL 499315a1350SMichael S. Tsirkin * [[<domain>:]<bus>:]<slot>.<func>, return -1 on error 500315a1350SMichael S. Tsirkin */ 501315a1350SMichael S. Tsirkin static int pci_parse_devaddr(const char *addr, int *domp, int *busp, 502315a1350SMichael S. Tsirkin unsigned int *slotp, unsigned int *funcp) 503315a1350SMichael S. Tsirkin { 504315a1350SMichael S. Tsirkin const char *p; 505315a1350SMichael S. Tsirkin char *e; 506315a1350SMichael S. Tsirkin unsigned long val; 507315a1350SMichael S. Tsirkin unsigned long dom = 0, bus = 0; 508315a1350SMichael S. Tsirkin unsigned int slot = 0; 509315a1350SMichael S. Tsirkin unsigned int func = 0; 510315a1350SMichael S. Tsirkin 511315a1350SMichael S. Tsirkin p = addr; 512315a1350SMichael S. Tsirkin val = strtoul(p, &e, 16); 513315a1350SMichael S. Tsirkin if (e == p) 514315a1350SMichael S. Tsirkin return -1; 515315a1350SMichael S. Tsirkin if (*e == ':') { 516315a1350SMichael S. Tsirkin bus = val; 517315a1350SMichael S. Tsirkin p = e + 1; 518315a1350SMichael S. Tsirkin val = strtoul(p, &e, 16); 519315a1350SMichael S. Tsirkin if (e == p) 520315a1350SMichael S. Tsirkin return -1; 521315a1350SMichael S. Tsirkin if (*e == ':') { 522315a1350SMichael S. Tsirkin dom = bus; 523315a1350SMichael S. Tsirkin bus = val; 524315a1350SMichael S. Tsirkin p = e + 1; 525315a1350SMichael S. Tsirkin val = strtoul(p, &e, 16); 526315a1350SMichael S. Tsirkin if (e == p) 527315a1350SMichael S. Tsirkin return -1; 528315a1350SMichael S. Tsirkin } 529315a1350SMichael S. Tsirkin } 530315a1350SMichael S. Tsirkin 531315a1350SMichael S. Tsirkin slot = val; 532315a1350SMichael S. Tsirkin 533315a1350SMichael S. Tsirkin if (funcp != NULL) { 534315a1350SMichael S. Tsirkin if (*e != '.') 535315a1350SMichael S. Tsirkin return -1; 536315a1350SMichael S. Tsirkin 537315a1350SMichael S. Tsirkin p = e + 1; 538315a1350SMichael S. Tsirkin val = strtoul(p, &e, 16); 539315a1350SMichael S. Tsirkin if (e == p) 540315a1350SMichael S. Tsirkin return -1; 541315a1350SMichael S. Tsirkin 542315a1350SMichael S. Tsirkin func = val; 543315a1350SMichael S. Tsirkin } 544315a1350SMichael S. Tsirkin 545315a1350SMichael S. Tsirkin /* if funcp == NULL func is 0 */ 546315a1350SMichael S. Tsirkin if (dom > 0xffff || bus > 0xff || slot > 0x1f || func > 7) 547315a1350SMichael S. Tsirkin return -1; 548315a1350SMichael S. Tsirkin 549315a1350SMichael S. Tsirkin if (*e) 550315a1350SMichael S. Tsirkin return -1; 551315a1350SMichael S. Tsirkin 552315a1350SMichael S. Tsirkin *domp = dom; 553315a1350SMichael S. Tsirkin *busp = bus; 554315a1350SMichael S. Tsirkin *slotp = slot; 555315a1350SMichael S. Tsirkin if (funcp != NULL) 556315a1350SMichael S. Tsirkin *funcp = func; 557315a1350SMichael S. Tsirkin return 0; 558315a1350SMichael S. Tsirkin } 559315a1350SMichael S. Tsirkin 560315a1350SMichael S. Tsirkin int pci_read_devaddr(Monitor *mon, const char *addr, int *domp, int *busp, 561315a1350SMichael S. Tsirkin unsigned *slotp) 562315a1350SMichael S. Tsirkin { 563315a1350SMichael S. Tsirkin /* strip legacy tag */ 564315a1350SMichael S. Tsirkin if (!strncmp(addr, "pci_addr=", 9)) { 565315a1350SMichael S. Tsirkin addr += 9; 566315a1350SMichael S. Tsirkin } 567315a1350SMichael S. Tsirkin if (pci_parse_devaddr(addr, domp, busp, slotp, NULL)) { 568315a1350SMichael S. Tsirkin monitor_printf(mon, "Invalid pci address\n"); 569315a1350SMichael S. Tsirkin return -1; 570315a1350SMichael S. Tsirkin } 571315a1350SMichael S. Tsirkin return 0; 572315a1350SMichael S. Tsirkin } 573315a1350SMichael S. Tsirkin 574315a1350SMichael S. Tsirkin PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr) 575315a1350SMichael S. Tsirkin { 576315a1350SMichael S. Tsirkin int dom, bus; 577315a1350SMichael S. Tsirkin unsigned slot; 578315a1350SMichael S. Tsirkin 579315a1350SMichael S. Tsirkin if (!devaddr) { 580315a1350SMichael S. Tsirkin *devfnp = -1; 581315a1350SMichael S. Tsirkin return pci_find_bus_nr(pci_find_root_bus(0), 0); 582315a1350SMichael S. Tsirkin } 583315a1350SMichael S. Tsirkin 584315a1350SMichael S. Tsirkin if (pci_parse_devaddr(devaddr, &dom, &bus, &slot, NULL) < 0) { 585315a1350SMichael S. Tsirkin return NULL; 586315a1350SMichael S. Tsirkin } 587315a1350SMichael S. Tsirkin 588315a1350SMichael S. Tsirkin *devfnp = PCI_DEVFN(slot, 0); 589315a1350SMichael S. Tsirkin return pci_find_bus_nr(pci_find_root_bus(dom), bus); 590315a1350SMichael S. Tsirkin } 591315a1350SMichael S. Tsirkin 592315a1350SMichael S. Tsirkin static void pci_init_cmask(PCIDevice *dev) 593315a1350SMichael S. Tsirkin { 594315a1350SMichael S. Tsirkin pci_set_word(dev->cmask + PCI_VENDOR_ID, 0xffff); 595315a1350SMichael S. Tsirkin pci_set_word(dev->cmask + PCI_DEVICE_ID, 0xffff); 596315a1350SMichael S. Tsirkin dev->cmask[PCI_STATUS] = PCI_STATUS_CAP_LIST; 597315a1350SMichael S. Tsirkin dev->cmask[PCI_REVISION_ID] = 0xff; 598315a1350SMichael S. Tsirkin dev->cmask[PCI_CLASS_PROG] = 0xff; 599315a1350SMichael S. Tsirkin pci_set_word(dev->cmask + PCI_CLASS_DEVICE, 0xffff); 600315a1350SMichael S. Tsirkin dev->cmask[PCI_HEADER_TYPE] = 0xff; 601315a1350SMichael S. Tsirkin dev->cmask[PCI_CAPABILITY_LIST] = 0xff; 602315a1350SMichael S. Tsirkin } 603315a1350SMichael S. Tsirkin 604315a1350SMichael S. Tsirkin static void pci_init_wmask(PCIDevice *dev) 605315a1350SMichael S. Tsirkin { 606315a1350SMichael S. Tsirkin int config_size = pci_config_size(dev); 607315a1350SMichael S. Tsirkin 608315a1350SMichael S. Tsirkin dev->wmask[PCI_CACHE_LINE_SIZE] = 0xff; 609315a1350SMichael S. Tsirkin dev->wmask[PCI_INTERRUPT_LINE] = 0xff; 610315a1350SMichael S. Tsirkin pci_set_word(dev->wmask + PCI_COMMAND, 611315a1350SMichael S. Tsirkin PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | 612315a1350SMichael S. Tsirkin PCI_COMMAND_INTX_DISABLE); 613315a1350SMichael S. Tsirkin if (dev->cap_present & QEMU_PCI_CAP_SERR) { 614315a1350SMichael S. Tsirkin pci_word_test_and_set_mask(dev->wmask + PCI_COMMAND, PCI_COMMAND_SERR); 615315a1350SMichael S. Tsirkin } 616315a1350SMichael S. Tsirkin 617315a1350SMichael S. Tsirkin memset(dev->wmask + PCI_CONFIG_HEADER_SIZE, 0xff, 618315a1350SMichael S. Tsirkin config_size - PCI_CONFIG_HEADER_SIZE); 619315a1350SMichael S. Tsirkin } 620315a1350SMichael S. Tsirkin 621315a1350SMichael S. Tsirkin static void pci_init_w1cmask(PCIDevice *dev) 622315a1350SMichael S. Tsirkin { 623315a1350SMichael S. Tsirkin /* 624315a1350SMichael S. Tsirkin * Note: It's okay to set w1cmask even for readonly bits as 625315a1350SMichael S. Tsirkin * long as their value is hardwired to 0. 626315a1350SMichael S. Tsirkin */ 627315a1350SMichael S. Tsirkin pci_set_word(dev->w1cmask + PCI_STATUS, 628315a1350SMichael S. Tsirkin PCI_STATUS_PARITY | PCI_STATUS_SIG_TARGET_ABORT | 629315a1350SMichael S. Tsirkin PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_REC_MASTER_ABORT | 630315a1350SMichael S. Tsirkin PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY); 631315a1350SMichael S. Tsirkin } 632315a1350SMichael S. Tsirkin 633315a1350SMichael S. Tsirkin static void pci_init_mask_bridge(PCIDevice *d) 634315a1350SMichael S. Tsirkin { 635315a1350SMichael S. Tsirkin /* PCI_PRIMARY_BUS, PCI_SECONDARY_BUS, PCI_SUBORDINATE_BUS and 636315a1350SMichael S. Tsirkin PCI_SEC_LETENCY_TIMER */ 637315a1350SMichael S. Tsirkin memset(d->wmask + PCI_PRIMARY_BUS, 0xff, 4); 638315a1350SMichael S. Tsirkin 639315a1350SMichael S. Tsirkin /* base and limit */ 640315a1350SMichael S. Tsirkin d->wmask[PCI_IO_BASE] = PCI_IO_RANGE_MASK & 0xff; 641315a1350SMichael S. Tsirkin d->wmask[PCI_IO_LIMIT] = PCI_IO_RANGE_MASK & 0xff; 642315a1350SMichael S. Tsirkin pci_set_word(d->wmask + PCI_MEMORY_BASE, 643315a1350SMichael S. Tsirkin PCI_MEMORY_RANGE_MASK & 0xffff); 644315a1350SMichael S. Tsirkin pci_set_word(d->wmask + PCI_MEMORY_LIMIT, 645315a1350SMichael S. Tsirkin PCI_MEMORY_RANGE_MASK & 0xffff); 646315a1350SMichael S. Tsirkin pci_set_word(d->wmask + PCI_PREF_MEMORY_BASE, 647315a1350SMichael S. Tsirkin PCI_PREF_RANGE_MASK & 0xffff); 648315a1350SMichael S. Tsirkin pci_set_word(d->wmask + PCI_PREF_MEMORY_LIMIT, 649315a1350SMichael S. Tsirkin PCI_PREF_RANGE_MASK & 0xffff); 650315a1350SMichael S. Tsirkin 651315a1350SMichael S. Tsirkin /* PCI_PREF_BASE_UPPER32 and PCI_PREF_LIMIT_UPPER32 */ 652315a1350SMichael S. Tsirkin memset(d->wmask + PCI_PREF_BASE_UPPER32, 0xff, 8); 653315a1350SMichael S. Tsirkin 654315a1350SMichael S. Tsirkin /* Supported memory and i/o types */ 655315a1350SMichael S. Tsirkin d->config[PCI_IO_BASE] |= PCI_IO_RANGE_TYPE_16; 656315a1350SMichael S. Tsirkin d->config[PCI_IO_LIMIT] |= PCI_IO_RANGE_TYPE_16; 657315a1350SMichael S. Tsirkin pci_word_test_and_set_mask(d->config + PCI_PREF_MEMORY_BASE, 658315a1350SMichael S. Tsirkin PCI_PREF_RANGE_TYPE_64); 659315a1350SMichael S. Tsirkin pci_word_test_and_set_mask(d->config + PCI_PREF_MEMORY_LIMIT, 660315a1350SMichael S. Tsirkin PCI_PREF_RANGE_TYPE_64); 661315a1350SMichael S. Tsirkin 662315a1350SMichael S. Tsirkin /* TODO: add this define to pci_regs.h in linux and then in qemu. */ 663315a1350SMichael S. Tsirkin #define PCI_BRIDGE_CTL_VGA_16BIT 0x10 /* VGA 16-bit decode */ 664315a1350SMichael S. Tsirkin #define PCI_BRIDGE_CTL_DISCARD 0x100 /* Primary discard timer */ 665315a1350SMichael S. Tsirkin #define PCI_BRIDGE_CTL_SEC_DISCARD 0x200 /* Secondary discard timer */ 666315a1350SMichael S. Tsirkin #define PCI_BRIDGE_CTL_DISCARD_STATUS 0x400 /* Discard timer status */ 667315a1350SMichael S. Tsirkin #define PCI_BRIDGE_CTL_DISCARD_SERR 0x800 /* Discard timer SERR# enable */ 668315a1350SMichael S. Tsirkin pci_set_word(d->wmask + PCI_BRIDGE_CONTROL, 669315a1350SMichael S. Tsirkin PCI_BRIDGE_CTL_PARITY | 670315a1350SMichael S. Tsirkin PCI_BRIDGE_CTL_SERR | 671315a1350SMichael S. Tsirkin PCI_BRIDGE_CTL_ISA | 672315a1350SMichael S. Tsirkin PCI_BRIDGE_CTL_VGA | 673315a1350SMichael S. Tsirkin PCI_BRIDGE_CTL_VGA_16BIT | 674315a1350SMichael S. Tsirkin PCI_BRIDGE_CTL_MASTER_ABORT | 675315a1350SMichael S. Tsirkin PCI_BRIDGE_CTL_BUS_RESET | 676315a1350SMichael S. Tsirkin PCI_BRIDGE_CTL_FAST_BACK | 677315a1350SMichael S. Tsirkin PCI_BRIDGE_CTL_DISCARD | 678315a1350SMichael S. Tsirkin PCI_BRIDGE_CTL_SEC_DISCARD | 679315a1350SMichael S. Tsirkin PCI_BRIDGE_CTL_DISCARD_SERR); 680315a1350SMichael S. Tsirkin /* Below does not do anything as we never set this bit, put here for 681315a1350SMichael S. Tsirkin * completeness. */ 682315a1350SMichael S. Tsirkin pci_set_word(d->w1cmask + PCI_BRIDGE_CONTROL, 683315a1350SMichael S. Tsirkin PCI_BRIDGE_CTL_DISCARD_STATUS); 684315a1350SMichael S. Tsirkin d->cmask[PCI_IO_BASE] |= PCI_IO_RANGE_TYPE_MASK; 685315a1350SMichael S. Tsirkin d->cmask[PCI_IO_LIMIT] |= PCI_IO_RANGE_TYPE_MASK; 686315a1350SMichael S. Tsirkin pci_word_test_and_set_mask(d->cmask + PCI_PREF_MEMORY_BASE, 687315a1350SMichael S. Tsirkin PCI_PREF_RANGE_TYPE_MASK); 688315a1350SMichael S. Tsirkin pci_word_test_and_set_mask(d->cmask + PCI_PREF_MEMORY_LIMIT, 689315a1350SMichael S. Tsirkin PCI_PREF_RANGE_TYPE_MASK); 690315a1350SMichael S. Tsirkin } 691315a1350SMichael S. Tsirkin 692315a1350SMichael S. Tsirkin static int pci_init_multifunction(PCIBus *bus, PCIDevice *dev) 693315a1350SMichael S. Tsirkin { 694315a1350SMichael S. Tsirkin uint8_t slot = PCI_SLOT(dev->devfn); 695315a1350SMichael S. Tsirkin uint8_t func; 696315a1350SMichael S. Tsirkin 697315a1350SMichael S. Tsirkin if (dev->cap_present & QEMU_PCI_CAP_MULTIFUNCTION) { 698315a1350SMichael S. Tsirkin dev->config[PCI_HEADER_TYPE] |= PCI_HEADER_TYPE_MULTI_FUNCTION; 699315a1350SMichael S. Tsirkin } 700315a1350SMichael S. Tsirkin 701315a1350SMichael S. Tsirkin /* 702315a1350SMichael S. Tsirkin * multifunction bit is interpreted in two ways as follows. 703315a1350SMichael S. Tsirkin * - all functions must set the bit to 1. 704315a1350SMichael S. Tsirkin * Example: Intel X53 705315a1350SMichael S. Tsirkin * - function 0 must set the bit, but the rest function (> 0) 706315a1350SMichael S. Tsirkin * is allowed to leave the bit to 0. 707315a1350SMichael S. Tsirkin * Example: PIIX3(also in qemu), PIIX4(also in qemu), ICH10, 708315a1350SMichael S. Tsirkin * 709315a1350SMichael S. Tsirkin * So OS (at least Linux) checks the bit of only function 0, 710315a1350SMichael S. Tsirkin * and doesn't see the bit of function > 0. 711315a1350SMichael S. Tsirkin * 712315a1350SMichael S. Tsirkin * The below check allows both interpretation. 713315a1350SMichael S. Tsirkin */ 714315a1350SMichael S. Tsirkin if (PCI_FUNC(dev->devfn)) { 715315a1350SMichael S. Tsirkin PCIDevice *f0 = bus->devices[PCI_DEVFN(slot, 0)]; 716315a1350SMichael S. Tsirkin if (f0 && !(f0->cap_present & QEMU_PCI_CAP_MULTIFUNCTION)) { 717315a1350SMichael S. Tsirkin /* function 0 should set multifunction bit */ 718315a1350SMichael S. Tsirkin error_report("PCI: single function device can't be populated " 719315a1350SMichael S. Tsirkin "in function %x.%x", slot, PCI_FUNC(dev->devfn)); 720315a1350SMichael S. Tsirkin return -1; 721315a1350SMichael S. Tsirkin } 722315a1350SMichael S. Tsirkin return 0; 723315a1350SMichael S. Tsirkin } 724315a1350SMichael S. Tsirkin 725315a1350SMichael S. Tsirkin if (dev->cap_present & QEMU_PCI_CAP_MULTIFUNCTION) { 726315a1350SMichael S. Tsirkin return 0; 727315a1350SMichael S. Tsirkin } 728315a1350SMichael S. Tsirkin /* function 0 indicates single function, so function > 0 must be NULL */ 729315a1350SMichael S. Tsirkin for (func = 1; func < PCI_FUNC_MAX; ++func) { 730315a1350SMichael S. Tsirkin if (bus->devices[PCI_DEVFN(slot, func)]) { 731315a1350SMichael S. Tsirkin error_report("PCI: %x.0 indicates single function, " 732315a1350SMichael S. Tsirkin "but %x.%x is already populated.", 733315a1350SMichael S. Tsirkin slot, slot, func); 734315a1350SMichael S. Tsirkin return -1; 735315a1350SMichael S. Tsirkin } 736315a1350SMichael S. Tsirkin } 737315a1350SMichael S. Tsirkin return 0; 738315a1350SMichael S. Tsirkin } 739315a1350SMichael S. Tsirkin 740315a1350SMichael S. Tsirkin static void pci_config_alloc(PCIDevice *pci_dev) 741315a1350SMichael S. Tsirkin { 742315a1350SMichael S. Tsirkin int config_size = pci_config_size(pci_dev); 743315a1350SMichael S. Tsirkin 744315a1350SMichael S. Tsirkin pci_dev->config = g_malloc0(config_size); 745315a1350SMichael S. Tsirkin pci_dev->cmask = g_malloc0(config_size); 746315a1350SMichael S. Tsirkin pci_dev->wmask = g_malloc0(config_size); 747315a1350SMichael S. Tsirkin pci_dev->w1cmask = g_malloc0(config_size); 748315a1350SMichael S. Tsirkin pci_dev->used = g_malloc0(config_size); 749315a1350SMichael S. Tsirkin } 750315a1350SMichael S. Tsirkin 751315a1350SMichael S. Tsirkin static void pci_config_free(PCIDevice *pci_dev) 752315a1350SMichael S. Tsirkin { 753315a1350SMichael S. Tsirkin g_free(pci_dev->config); 754315a1350SMichael S. Tsirkin g_free(pci_dev->cmask); 755315a1350SMichael S. Tsirkin g_free(pci_dev->wmask); 756315a1350SMichael S. Tsirkin g_free(pci_dev->w1cmask); 757315a1350SMichael S. Tsirkin g_free(pci_dev->used); 758315a1350SMichael S. Tsirkin } 759315a1350SMichael S. Tsirkin 760315a1350SMichael S. Tsirkin /* -1 for devfn means auto assign */ 761315a1350SMichael S. Tsirkin static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus, 762315a1350SMichael S. Tsirkin const char *name, int devfn) 763315a1350SMichael S. Tsirkin { 764315a1350SMichael S. Tsirkin PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev); 765315a1350SMichael S. Tsirkin PCIConfigReadFunc *config_read = pc->config_read; 766315a1350SMichael S. Tsirkin PCIConfigWriteFunc *config_write = pc->config_write; 767315a1350SMichael S. Tsirkin 768315a1350SMichael S. Tsirkin if (devfn < 0) { 769315a1350SMichael S. Tsirkin for(devfn = bus->devfn_min ; devfn < ARRAY_SIZE(bus->devices); 770315a1350SMichael S. Tsirkin devfn += PCI_FUNC_MAX) { 771315a1350SMichael S. Tsirkin if (!bus->devices[devfn]) 772315a1350SMichael S. Tsirkin goto found; 773315a1350SMichael S. Tsirkin } 774315a1350SMichael S. Tsirkin error_report("PCI: no slot/function available for %s, all in use", name); 775315a1350SMichael S. Tsirkin return NULL; 776315a1350SMichael S. Tsirkin found: ; 777315a1350SMichael S. Tsirkin } else if (bus->devices[devfn]) { 778315a1350SMichael S. Tsirkin error_report("PCI: slot %d function %d not available for %s, in use by %s", 779315a1350SMichael S. Tsirkin PCI_SLOT(devfn), PCI_FUNC(devfn), name, bus->devices[devfn]->name); 780315a1350SMichael S. Tsirkin return NULL; 781315a1350SMichael S. Tsirkin } 782315a1350SMichael S. Tsirkin pci_dev->bus = bus; 783315a1350SMichael S. Tsirkin if (bus->dma_context_fn) { 784315a1350SMichael S. Tsirkin pci_dev->dma = bus->dma_context_fn(bus, bus->dma_context_opaque, devfn); 785315a1350SMichael S. Tsirkin } else { 786315a1350SMichael S. Tsirkin /* FIXME: Make dma_context_fn use MemoryRegions instead, so this path is 787315a1350SMichael S. Tsirkin * taken unconditionally */ 788315a1350SMichael S. Tsirkin /* FIXME: inherit memory region from bus creator */ 789315a1350SMichael S. Tsirkin memory_region_init_alias(&pci_dev->bus_master_enable_region, "bus master", 790315a1350SMichael S. Tsirkin get_system_memory(), 0, 791315a1350SMichael S. Tsirkin memory_region_size(get_system_memory())); 792315a1350SMichael S. Tsirkin memory_region_set_enabled(&pci_dev->bus_master_enable_region, false); 793315a1350SMichael S. Tsirkin address_space_init(&pci_dev->bus_master_as, &pci_dev->bus_master_enable_region); 794315a1350SMichael S. Tsirkin pci_dev->dma = g_new(DMAContext, 1); 795315a1350SMichael S. Tsirkin dma_context_init(pci_dev->dma, &pci_dev->bus_master_as, NULL, NULL, NULL); 796315a1350SMichael S. Tsirkin } 797315a1350SMichael S. Tsirkin pci_dev->devfn = devfn; 798315a1350SMichael S. Tsirkin pstrcpy(pci_dev->name, sizeof(pci_dev->name), name); 799315a1350SMichael S. Tsirkin pci_dev->irq_state = 0; 800315a1350SMichael S. Tsirkin pci_config_alloc(pci_dev); 801315a1350SMichael S. Tsirkin 802315a1350SMichael S. Tsirkin pci_config_set_vendor_id(pci_dev->config, pc->vendor_id); 803315a1350SMichael S. Tsirkin pci_config_set_device_id(pci_dev->config, pc->device_id); 804315a1350SMichael S. Tsirkin pci_config_set_revision(pci_dev->config, pc->revision); 805315a1350SMichael S. Tsirkin pci_config_set_class(pci_dev->config, pc->class_id); 806315a1350SMichael S. Tsirkin 807315a1350SMichael S. Tsirkin if (!pc->is_bridge) { 808315a1350SMichael S. Tsirkin if (pc->subsystem_vendor_id || pc->subsystem_id) { 809315a1350SMichael S. Tsirkin pci_set_word(pci_dev->config + PCI_SUBSYSTEM_VENDOR_ID, 810315a1350SMichael S. Tsirkin pc->subsystem_vendor_id); 811315a1350SMichael S. Tsirkin pci_set_word(pci_dev->config + PCI_SUBSYSTEM_ID, 812315a1350SMichael S. Tsirkin pc->subsystem_id); 813315a1350SMichael S. Tsirkin } else { 814315a1350SMichael S. Tsirkin pci_set_default_subsystem_id(pci_dev); 815315a1350SMichael S. Tsirkin } 816315a1350SMichael S. Tsirkin } else { 817315a1350SMichael S. Tsirkin /* subsystem_vendor_id/subsystem_id are only for header type 0 */ 818315a1350SMichael S. Tsirkin assert(!pc->subsystem_vendor_id); 819315a1350SMichael S. Tsirkin assert(!pc->subsystem_id); 820315a1350SMichael S. Tsirkin } 821315a1350SMichael S. Tsirkin pci_init_cmask(pci_dev); 822315a1350SMichael S. Tsirkin pci_init_wmask(pci_dev); 823315a1350SMichael S. Tsirkin pci_init_w1cmask(pci_dev); 824315a1350SMichael S. Tsirkin if (pc->is_bridge) { 825315a1350SMichael S. Tsirkin pci_init_mask_bridge(pci_dev); 826315a1350SMichael S. Tsirkin } 827315a1350SMichael S. Tsirkin if (pci_init_multifunction(bus, pci_dev)) { 828315a1350SMichael S. Tsirkin pci_config_free(pci_dev); 829315a1350SMichael S. Tsirkin return NULL; 830315a1350SMichael S. Tsirkin } 831315a1350SMichael S. Tsirkin 832315a1350SMichael S. Tsirkin if (!config_read) 833315a1350SMichael S. Tsirkin config_read = pci_default_read_config; 834315a1350SMichael S. Tsirkin if (!config_write) 835315a1350SMichael S. Tsirkin config_write = pci_default_write_config; 836315a1350SMichael S. Tsirkin pci_dev->config_read = config_read; 837315a1350SMichael S. Tsirkin pci_dev->config_write = config_write; 838315a1350SMichael S. Tsirkin bus->devices[devfn] = pci_dev; 839315a1350SMichael S. Tsirkin pci_dev->irq = qemu_allocate_irqs(pci_set_irq, pci_dev, PCI_NUM_PINS); 840315a1350SMichael S. Tsirkin pci_dev->version_id = 2; /* Current pci device vmstate version */ 841315a1350SMichael S. Tsirkin return pci_dev; 842315a1350SMichael S. Tsirkin } 843315a1350SMichael S. Tsirkin 844315a1350SMichael S. Tsirkin static void do_pci_unregister_device(PCIDevice *pci_dev) 845315a1350SMichael S. Tsirkin { 846315a1350SMichael S. Tsirkin qemu_free_irqs(pci_dev->irq); 847315a1350SMichael S. Tsirkin pci_dev->bus->devices[pci_dev->devfn] = NULL; 848315a1350SMichael S. Tsirkin pci_config_free(pci_dev); 849315a1350SMichael S. Tsirkin 850315a1350SMichael S. Tsirkin if (!pci_dev->bus->dma_context_fn) { 851315a1350SMichael S. Tsirkin address_space_destroy(&pci_dev->bus_master_as); 852315a1350SMichael S. Tsirkin memory_region_destroy(&pci_dev->bus_master_enable_region); 853315a1350SMichael S. Tsirkin g_free(pci_dev->dma); 854315a1350SMichael S. Tsirkin pci_dev->dma = NULL; 855315a1350SMichael S. Tsirkin } 856315a1350SMichael S. Tsirkin } 857315a1350SMichael S. Tsirkin 858315a1350SMichael S. Tsirkin static void pci_unregister_io_regions(PCIDevice *pci_dev) 859315a1350SMichael S. Tsirkin { 860315a1350SMichael S. Tsirkin PCIIORegion *r; 861315a1350SMichael S. Tsirkin int i; 862315a1350SMichael S. Tsirkin 863315a1350SMichael S. Tsirkin for(i = 0; i < PCI_NUM_REGIONS; i++) { 864315a1350SMichael S. Tsirkin r = &pci_dev->io_regions[i]; 865315a1350SMichael S. Tsirkin if (!r->size || r->addr == PCI_BAR_UNMAPPED) 866315a1350SMichael S. Tsirkin continue; 867315a1350SMichael S. Tsirkin memory_region_del_subregion(r->address_space, r->memory); 868315a1350SMichael S. Tsirkin } 869315a1350SMichael S. Tsirkin } 870315a1350SMichael S. Tsirkin 871315a1350SMichael S. Tsirkin static int pci_unregister_device(DeviceState *dev) 872315a1350SMichael S. Tsirkin { 873315a1350SMichael S. Tsirkin PCIDevice *pci_dev = PCI_DEVICE(dev); 874315a1350SMichael S. Tsirkin PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev); 875315a1350SMichael S. Tsirkin 876315a1350SMichael S. Tsirkin pci_unregister_io_regions(pci_dev); 877315a1350SMichael S. Tsirkin pci_del_option_rom(pci_dev); 878315a1350SMichael S. Tsirkin 879315a1350SMichael S. Tsirkin if (pc->exit) { 880315a1350SMichael S. Tsirkin pc->exit(pci_dev); 881315a1350SMichael S. Tsirkin } 882315a1350SMichael S. Tsirkin 883315a1350SMichael S. Tsirkin do_pci_unregister_device(pci_dev); 884315a1350SMichael S. Tsirkin return 0; 885315a1350SMichael S. Tsirkin } 886315a1350SMichael S. Tsirkin 887315a1350SMichael S. Tsirkin void pci_register_bar(PCIDevice *pci_dev, int region_num, 888315a1350SMichael S. Tsirkin uint8_t type, MemoryRegion *memory) 889315a1350SMichael S. Tsirkin { 890315a1350SMichael S. Tsirkin PCIIORegion *r; 891315a1350SMichael S. Tsirkin uint32_t addr; 892315a1350SMichael S. Tsirkin uint64_t wmask; 893315a1350SMichael S. Tsirkin pcibus_t size = memory_region_size(memory); 894315a1350SMichael S. Tsirkin 895315a1350SMichael S. Tsirkin assert(region_num >= 0); 896315a1350SMichael S. Tsirkin assert(region_num < PCI_NUM_REGIONS); 897315a1350SMichael S. Tsirkin if (size & (size-1)) { 898315a1350SMichael S. Tsirkin fprintf(stderr, "ERROR: PCI region size must be pow2 " 899315a1350SMichael S. Tsirkin "type=0x%x, size=0x%"FMT_PCIBUS"\n", type, size); 900315a1350SMichael S. Tsirkin exit(1); 901315a1350SMichael S. Tsirkin } 902315a1350SMichael S. Tsirkin 903315a1350SMichael S. Tsirkin r = &pci_dev->io_regions[region_num]; 904315a1350SMichael S. Tsirkin r->addr = PCI_BAR_UNMAPPED; 905315a1350SMichael S. Tsirkin r->size = size; 906315a1350SMichael S. Tsirkin r->type = type; 907315a1350SMichael S. Tsirkin r->memory = NULL; 908315a1350SMichael S. Tsirkin 909315a1350SMichael S. Tsirkin wmask = ~(size - 1); 910315a1350SMichael S. Tsirkin addr = pci_bar(pci_dev, region_num); 911315a1350SMichael S. Tsirkin if (region_num == PCI_ROM_SLOT) { 912315a1350SMichael S. Tsirkin /* ROM enable bit is writable */ 913315a1350SMichael S. Tsirkin wmask |= PCI_ROM_ADDRESS_ENABLE; 914315a1350SMichael S. Tsirkin } 915315a1350SMichael S. Tsirkin pci_set_long(pci_dev->config + addr, type); 916315a1350SMichael S. Tsirkin if (!(r->type & PCI_BASE_ADDRESS_SPACE_IO) && 917315a1350SMichael S. Tsirkin r->type & PCI_BASE_ADDRESS_MEM_TYPE_64) { 918315a1350SMichael S. Tsirkin pci_set_quad(pci_dev->wmask + addr, wmask); 919315a1350SMichael S. Tsirkin pci_set_quad(pci_dev->cmask + addr, ~0ULL); 920315a1350SMichael S. Tsirkin } else { 921315a1350SMichael S. Tsirkin pci_set_long(pci_dev->wmask + addr, wmask & 0xffffffff); 922315a1350SMichael S. Tsirkin pci_set_long(pci_dev->cmask + addr, 0xffffffff); 923315a1350SMichael S. Tsirkin } 924315a1350SMichael S. Tsirkin pci_dev->io_regions[region_num].memory = memory; 925315a1350SMichael S. Tsirkin pci_dev->io_regions[region_num].address_space 926315a1350SMichael S. Tsirkin = type & PCI_BASE_ADDRESS_SPACE_IO 927315a1350SMichael S. Tsirkin ? pci_dev->bus->address_space_io 928315a1350SMichael S. Tsirkin : pci_dev->bus->address_space_mem; 929315a1350SMichael S. Tsirkin } 930315a1350SMichael S. Tsirkin 931315a1350SMichael S. Tsirkin pcibus_t pci_get_bar_addr(PCIDevice *pci_dev, int region_num) 932315a1350SMichael S. Tsirkin { 933315a1350SMichael S. Tsirkin return pci_dev->io_regions[region_num].addr; 934315a1350SMichael S. Tsirkin } 935315a1350SMichael S. Tsirkin 936315a1350SMichael S. Tsirkin static pcibus_t pci_bar_address(PCIDevice *d, 937315a1350SMichael S. Tsirkin int reg, uint8_t type, pcibus_t size) 938315a1350SMichael S. Tsirkin { 939315a1350SMichael S. Tsirkin pcibus_t new_addr, last_addr; 940315a1350SMichael S. Tsirkin int bar = pci_bar(d, reg); 941315a1350SMichael S. Tsirkin uint16_t cmd = pci_get_word(d->config + PCI_COMMAND); 942315a1350SMichael S. Tsirkin 943315a1350SMichael S. Tsirkin if (type & PCI_BASE_ADDRESS_SPACE_IO) { 944315a1350SMichael S. Tsirkin if (!(cmd & PCI_COMMAND_IO)) { 945315a1350SMichael S. Tsirkin return PCI_BAR_UNMAPPED; 946315a1350SMichael S. Tsirkin } 947315a1350SMichael S. Tsirkin new_addr = pci_get_long(d->config + bar) & ~(size - 1); 948315a1350SMichael S. Tsirkin last_addr = new_addr + size - 1; 949315a1350SMichael S. Tsirkin /* NOTE: we have only 64K ioports on PC */ 950315a1350SMichael S. Tsirkin if (last_addr <= new_addr || new_addr == 0 || last_addr > UINT16_MAX) { 951315a1350SMichael S. Tsirkin return PCI_BAR_UNMAPPED; 952315a1350SMichael S. Tsirkin } 953315a1350SMichael S. Tsirkin return new_addr; 954315a1350SMichael S. Tsirkin } 955315a1350SMichael S. Tsirkin 956315a1350SMichael S. Tsirkin if (!(cmd & PCI_COMMAND_MEMORY)) { 957315a1350SMichael S. Tsirkin return PCI_BAR_UNMAPPED; 958315a1350SMichael S. Tsirkin } 959315a1350SMichael S. Tsirkin if (type & PCI_BASE_ADDRESS_MEM_TYPE_64) { 960315a1350SMichael S. Tsirkin new_addr = pci_get_quad(d->config + bar); 961315a1350SMichael S. Tsirkin } else { 962315a1350SMichael S. Tsirkin new_addr = pci_get_long(d->config + bar); 963315a1350SMichael S. Tsirkin } 964315a1350SMichael S. Tsirkin /* the ROM slot has a specific enable bit */ 965315a1350SMichael S. Tsirkin if (reg == PCI_ROM_SLOT && !(new_addr & PCI_ROM_ADDRESS_ENABLE)) { 966315a1350SMichael S. Tsirkin return PCI_BAR_UNMAPPED; 967315a1350SMichael S. Tsirkin } 968315a1350SMichael S. Tsirkin new_addr &= ~(size - 1); 969315a1350SMichael S. Tsirkin last_addr = new_addr + size - 1; 970315a1350SMichael S. Tsirkin /* NOTE: we do not support wrapping */ 971315a1350SMichael S. Tsirkin /* XXX: as we cannot support really dynamic 972315a1350SMichael S. Tsirkin mappings, we handle specific values as invalid 973315a1350SMichael S. Tsirkin mappings. */ 974315a1350SMichael S. Tsirkin if (last_addr <= new_addr || new_addr == 0 || 975315a1350SMichael S. Tsirkin last_addr == PCI_BAR_UNMAPPED) { 976315a1350SMichael S. Tsirkin return PCI_BAR_UNMAPPED; 977315a1350SMichael S. Tsirkin } 978315a1350SMichael S. Tsirkin 979315a1350SMichael S. Tsirkin /* Now pcibus_t is 64bit. 980315a1350SMichael S. Tsirkin * Check if 32 bit BAR wraps around explicitly. 981315a1350SMichael S. Tsirkin * Without this, PC ide doesn't work well. 982315a1350SMichael S. Tsirkin * TODO: remove this work around. 983315a1350SMichael S. Tsirkin */ 984315a1350SMichael S. Tsirkin if (!(type & PCI_BASE_ADDRESS_MEM_TYPE_64) && last_addr >= UINT32_MAX) { 985315a1350SMichael S. Tsirkin return PCI_BAR_UNMAPPED; 986315a1350SMichael S. Tsirkin } 987315a1350SMichael S. Tsirkin 988315a1350SMichael S. Tsirkin /* 989315a1350SMichael S. Tsirkin * OS is allowed to set BAR beyond its addressable 990315a1350SMichael S. Tsirkin * bits. For example, 32 bit OS can set 64bit bar 991315a1350SMichael S. Tsirkin * to >4G. Check it. TODO: we might need to support 992315a1350SMichael S. Tsirkin * it in the future for e.g. PAE. 993315a1350SMichael S. Tsirkin */ 994315a1350SMichael S. Tsirkin if (last_addr >= HWADDR_MAX) { 995315a1350SMichael S. Tsirkin return PCI_BAR_UNMAPPED; 996315a1350SMichael S. Tsirkin } 997315a1350SMichael S. Tsirkin 998315a1350SMichael S. Tsirkin return new_addr; 999315a1350SMichael S. Tsirkin } 1000315a1350SMichael S. Tsirkin 1001315a1350SMichael S. Tsirkin static void pci_update_mappings(PCIDevice *d) 1002315a1350SMichael S. Tsirkin { 1003315a1350SMichael S. Tsirkin PCIIORegion *r; 1004315a1350SMichael S. Tsirkin int i; 1005315a1350SMichael S. Tsirkin pcibus_t new_addr; 1006315a1350SMichael S. Tsirkin 1007315a1350SMichael S. Tsirkin for(i = 0; i < PCI_NUM_REGIONS; i++) { 1008315a1350SMichael S. Tsirkin r = &d->io_regions[i]; 1009315a1350SMichael S. Tsirkin 1010315a1350SMichael S. Tsirkin /* this region isn't registered */ 1011315a1350SMichael S. Tsirkin if (!r->size) 1012315a1350SMichael S. Tsirkin continue; 1013315a1350SMichael S. Tsirkin 1014315a1350SMichael S. Tsirkin new_addr = pci_bar_address(d, i, r->type, r->size); 1015315a1350SMichael S. Tsirkin 1016315a1350SMichael S. Tsirkin /* This bar isn't changed */ 1017315a1350SMichael S. Tsirkin if (new_addr == r->addr) 1018315a1350SMichael S. Tsirkin continue; 1019315a1350SMichael S. Tsirkin 1020315a1350SMichael S. Tsirkin /* now do the real mapping */ 1021315a1350SMichael S. Tsirkin if (r->addr != PCI_BAR_UNMAPPED) { 1022315a1350SMichael S. Tsirkin memory_region_del_subregion(r->address_space, r->memory); 1023315a1350SMichael S. Tsirkin } 1024315a1350SMichael S. Tsirkin r->addr = new_addr; 1025315a1350SMichael S. Tsirkin if (r->addr != PCI_BAR_UNMAPPED) { 1026315a1350SMichael S. Tsirkin memory_region_add_subregion_overlap(r->address_space, 1027315a1350SMichael S. Tsirkin r->addr, r->memory, 1); 1028315a1350SMichael S. Tsirkin } 1029315a1350SMichael S. Tsirkin } 1030315a1350SMichael S. Tsirkin } 1031315a1350SMichael S. Tsirkin 1032315a1350SMichael S. Tsirkin static inline int pci_irq_disabled(PCIDevice *d) 1033315a1350SMichael S. Tsirkin { 1034315a1350SMichael S. Tsirkin return pci_get_word(d->config + PCI_COMMAND) & PCI_COMMAND_INTX_DISABLE; 1035315a1350SMichael S. Tsirkin } 1036315a1350SMichael S. Tsirkin 1037315a1350SMichael S. Tsirkin /* Called after interrupt disabled field update in config space, 1038315a1350SMichael S. Tsirkin * assert/deassert interrupts if necessary. 1039315a1350SMichael S. Tsirkin * Gets original interrupt disable bit value (before update). */ 1040315a1350SMichael S. Tsirkin static void pci_update_irq_disabled(PCIDevice *d, int was_irq_disabled) 1041315a1350SMichael S. Tsirkin { 1042315a1350SMichael S. Tsirkin int i, disabled = pci_irq_disabled(d); 1043315a1350SMichael S. Tsirkin if (disabled == was_irq_disabled) 1044315a1350SMichael S. Tsirkin return; 1045315a1350SMichael S. Tsirkin for (i = 0; i < PCI_NUM_PINS; ++i) { 1046315a1350SMichael S. Tsirkin int state = pci_irq_state(d, i); 1047315a1350SMichael S. Tsirkin pci_change_irq_level(d, i, disabled ? -state : state); 1048315a1350SMichael S. Tsirkin } 1049315a1350SMichael S. Tsirkin } 1050315a1350SMichael S. Tsirkin 1051315a1350SMichael S. Tsirkin uint32_t pci_default_read_config(PCIDevice *d, 1052315a1350SMichael S. Tsirkin uint32_t address, int len) 1053315a1350SMichael S. Tsirkin { 1054315a1350SMichael S. Tsirkin uint32_t val = 0; 1055315a1350SMichael S. Tsirkin 1056315a1350SMichael S. Tsirkin memcpy(&val, d->config + address, len); 1057315a1350SMichael S. Tsirkin return le32_to_cpu(val); 1058315a1350SMichael S. Tsirkin } 1059315a1350SMichael S. Tsirkin 1060315a1350SMichael S. Tsirkin void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l) 1061315a1350SMichael S. Tsirkin { 1062315a1350SMichael S. Tsirkin int i, was_irq_disabled = pci_irq_disabled(d); 1063315a1350SMichael S. Tsirkin 1064315a1350SMichael S. Tsirkin for (i = 0; i < l; val >>= 8, ++i) { 1065315a1350SMichael S. Tsirkin uint8_t wmask = d->wmask[addr + i]; 1066315a1350SMichael S. Tsirkin uint8_t w1cmask = d->w1cmask[addr + i]; 1067315a1350SMichael S. Tsirkin assert(!(wmask & w1cmask)); 1068315a1350SMichael S. Tsirkin d->config[addr + i] = (d->config[addr + i] & ~wmask) | (val & wmask); 1069315a1350SMichael S. Tsirkin d->config[addr + i] &= ~(val & w1cmask); /* W1C: Write 1 to Clear */ 1070315a1350SMichael S. Tsirkin } 1071315a1350SMichael S. Tsirkin if (ranges_overlap(addr, l, PCI_BASE_ADDRESS_0, 24) || 1072315a1350SMichael S. Tsirkin ranges_overlap(addr, l, PCI_ROM_ADDRESS, 4) || 1073315a1350SMichael S. Tsirkin ranges_overlap(addr, l, PCI_ROM_ADDRESS1, 4) || 1074315a1350SMichael S. Tsirkin range_covers_byte(addr, l, PCI_COMMAND)) 1075315a1350SMichael S. Tsirkin pci_update_mappings(d); 1076315a1350SMichael S. Tsirkin 1077315a1350SMichael S. Tsirkin if (range_covers_byte(addr, l, PCI_COMMAND)) { 1078315a1350SMichael S. Tsirkin pci_update_irq_disabled(d, was_irq_disabled); 1079315a1350SMichael S. Tsirkin memory_region_set_enabled(&d->bus_master_enable_region, 1080315a1350SMichael S. Tsirkin pci_get_word(d->config + PCI_COMMAND) 1081315a1350SMichael S. Tsirkin & PCI_COMMAND_MASTER); 1082315a1350SMichael S. Tsirkin } 1083315a1350SMichael S. Tsirkin 1084315a1350SMichael S. Tsirkin msi_write_config(d, addr, val, l); 1085315a1350SMichael S. Tsirkin msix_write_config(d, addr, val, l); 1086315a1350SMichael S. Tsirkin } 1087315a1350SMichael S. Tsirkin 1088315a1350SMichael S. Tsirkin /***********************************************************/ 1089315a1350SMichael S. Tsirkin /* generic PCI irq support */ 1090315a1350SMichael S. Tsirkin 1091315a1350SMichael S. Tsirkin /* 0 <= irq_num <= 3. level must be 0 or 1 */ 1092315a1350SMichael S. Tsirkin static void pci_set_irq(void *opaque, int irq_num, int level) 1093315a1350SMichael S. Tsirkin { 1094315a1350SMichael S. Tsirkin PCIDevice *pci_dev = opaque; 1095315a1350SMichael S. Tsirkin int change; 1096315a1350SMichael S. Tsirkin 1097315a1350SMichael S. Tsirkin change = level - pci_irq_state(pci_dev, irq_num); 1098315a1350SMichael S. Tsirkin if (!change) 1099315a1350SMichael S. Tsirkin return; 1100315a1350SMichael S. Tsirkin 1101315a1350SMichael S. Tsirkin pci_set_irq_state(pci_dev, irq_num, level); 1102315a1350SMichael S. Tsirkin pci_update_irq_status(pci_dev); 1103315a1350SMichael S. Tsirkin if (pci_irq_disabled(pci_dev)) 1104315a1350SMichael S. Tsirkin return; 1105315a1350SMichael S. Tsirkin pci_change_irq_level(pci_dev, irq_num, change); 1106315a1350SMichael S. Tsirkin } 1107315a1350SMichael S. Tsirkin 1108315a1350SMichael S. Tsirkin /* Special hooks used by device assignment */ 1109315a1350SMichael S. Tsirkin void pci_bus_set_route_irq_fn(PCIBus *bus, pci_route_irq_fn route_intx_to_irq) 1110315a1350SMichael S. Tsirkin { 1111315a1350SMichael S. Tsirkin assert(!bus->parent_dev); 1112315a1350SMichael S. Tsirkin bus->route_intx_to_irq = route_intx_to_irq; 1113315a1350SMichael S. Tsirkin } 1114315a1350SMichael S. Tsirkin 1115315a1350SMichael S. Tsirkin PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin) 1116315a1350SMichael S. Tsirkin { 1117315a1350SMichael S. Tsirkin PCIBus *bus; 1118315a1350SMichael S. Tsirkin 1119315a1350SMichael S. Tsirkin do { 1120315a1350SMichael S. Tsirkin bus = dev->bus; 1121315a1350SMichael S. Tsirkin pin = bus->map_irq(dev, pin); 1122315a1350SMichael S. Tsirkin dev = bus->parent_dev; 1123315a1350SMichael S. Tsirkin } while (dev); 1124315a1350SMichael S. Tsirkin 1125315a1350SMichael S. Tsirkin if (!bus->route_intx_to_irq) { 1126315a1350SMichael S. Tsirkin error_report("PCI: Bug - unimplemented PCI INTx routing (%s)\n", 1127315a1350SMichael S. Tsirkin object_get_typename(OBJECT(bus->qbus.parent))); 1128315a1350SMichael S. Tsirkin return (PCIINTxRoute) { PCI_INTX_DISABLED, -1 }; 1129315a1350SMichael S. Tsirkin } 1130315a1350SMichael S. Tsirkin 1131315a1350SMichael S. Tsirkin return bus->route_intx_to_irq(bus->irq_opaque, pin); 1132315a1350SMichael S. Tsirkin } 1133315a1350SMichael S. Tsirkin 1134315a1350SMichael S. Tsirkin bool pci_intx_route_changed(PCIINTxRoute *old, PCIINTxRoute *new) 1135315a1350SMichael S. Tsirkin { 1136315a1350SMichael S. Tsirkin return old->mode != new->mode || old->irq != new->irq; 1137315a1350SMichael S. Tsirkin } 1138315a1350SMichael S. Tsirkin 1139315a1350SMichael S. Tsirkin void pci_bus_fire_intx_routing_notifier(PCIBus *bus) 1140315a1350SMichael S. Tsirkin { 1141315a1350SMichael S. Tsirkin PCIDevice *dev; 1142315a1350SMichael S. Tsirkin PCIBus *sec; 1143315a1350SMichael S. Tsirkin int i; 1144315a1350SMichael S. Tsirkin 1145315a1350SMichael S. Tsirkin for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) { 1146315a1350SMichael S. Tsirkin dev = bus->devices[i]; 1147315a1350SMichael S. Tsirkin if (dev && dev->intx_routing_notifier) { 1148315a1350SMichael S. Tsirkin dev->intx_routing_notifier(dev); 1149315a1350SMichael S. Tsirkin } 1150315a1350SMichael S. Tsirkin QLIST_FOREACH(sec, &bus->child, sibling) { 1151315a1350SMichael S. Tsirkin pci_bus_fire_intx_routing_notifier(sec); 1152315a1350SMichael S. Tsirkin } 1153315a1350SMichael S. Tsirkin } 1154315a1350SMichael S. Tsirkin } 1155315a1350SMichael S. Tsirkin 1156315a1350SMichael S. Tsirkin void pci_device_set_intx_routing_notifier(PCIDevice *dev, 1157315a1350SMichael S. Tsirkin PCIINTxRoutingNotifier notifier) 1158315a1350SMichael S. Tsirkin { 1159315a1350SMichael S. Tsirkin dev->intx_routing_notifier = notifier; 1160315a1350SMichael S. Tsirkin } 1161315a1350SMichael S. Tsirkin 1162315a1350SMichael S. Tsirkin /* 1163315a1350SMichael S. Tsirkin * PCI-to-PCI bridge specification 1164315a1350SMichael S. Tsirkin * 9.1: Interrupt routing. Table 9-1 1165315a1350SMichael S. Tsirkin * 1166315a1350SMichael S. Tsirkin * the PCI Express Base Specification, Revision 2.1 1167315a1350SMichael S. Tsirkin * 2.2.8.1: INTx interrutp signaling - Rules 1168315a1350SMichael S. Tsirkin * the Implementation Note 1169315a1350SMichael S. Tsirkin * Table 2-20 1170315a1350SMichael S. Tsirkin */ 1171315a1350SMichael S. Tsirkin /* 1172315a1350SMichael S. Tsirkin * 0 <= pin <= 3 0 = INTA, 1 = INTB, 2 = INTC, 3 = INTD 1173315a1350SMichael S. Tsirkin * 0-origin unlike PCI interrupt pin register. 1174315a1350SMichael S. Tsirkin */ 1175315a1350SMichael S. Tsirkin int pci_swizzle_map_irq_fn(PCIDevice *pci_dev, int pin) 1176315a1350SMichael S. Tsirkin { 1177315a1350SMichael S. Tsirkin return (pin + PCI_SLOT(pci_dev->devfn)) % PCI_NUM_PINS; 1178315a1350SMichael S. Tsirkin } 1179315a1350SMichael S. Tsirkin 1180315a1350SMichael S. Tsirkin /***********************************************************/ 1181315a1350SMichael S. Tsirkin /* monitor info on PCI */ 1182315a1350SMichael S. Tsirkin 1183315a1350SMichael S. Tsirkin typedef struct { 1184315a1350SMichael S. Tsirkin uint16_t class; 1185315a1350SMichael S. Tsirkin const char *desc; 1186315a1350SMichael S. Tsirkin const char *fw_name; 1187315a1350SMichael S. Tsirkin uint16_t fw_ign_bits; 1188315a1350SMichael S. Tsirkin } pci_class_desc; 1189315a1350SMichael S. Tsirkin 1190315a1350SMichael S. Tsirkin static const pci_class_desc pci_class_descriptions[] = 1191315a1350SMichael S. Tsirkin { 1192315a1350SMichael S. Tsirkin { 0x0001, "VGA controller", "display"}, 1193315a1350SMichael S. Tsirkin { 0x0100, "SCSI controller", "scsi"}, 1194315a1350SMichael S. Tsirkin { 0x0101, "IDE controller", "ide"}, 1195315a1350SMichael S. Tsirkin { 0x0102, "Floppy controller", "fdc"}, 1196315a1350SMichael S. Tsirkin { 0x0103, "IPI controller", "ipi"}, 1197315a1350SMichael S. Tsirkin { 0x0104, "RAID controller", "raid"}, 1198315a1350SMichael S. Tsirkin { 0x0106, "SATA controller"}, 1199315a1350SMichael S. Tsirkin { 0x0107, "SAS controller"}, 1200315a1350SMichael S. Tsirkin { 0x0180, "Storage controller"}, 1201315a1350SMichael S. Tsirkin { 0x0200, "Ethernet controller", "ethernet"}, 1202315a1350SMichael S. Tsirkin { 0x0201, "Token Ring controller", "token-ring"}, 1203315a1350SMichael S. Tsirkin { 0x0202, "FDDI controller", "fddi"}, 1204315a1350SMichael S. Tsirkin { 0x0203, "ATM controller", "atm"}, 1205315a1350SMichael S. Tsirkin { 0x0280, "Network controller"}, 1206315a1350SMichael S. Tsirkin { 0x0300, "VGA controller", "display", 0x00ff}, 1207315a1350SMichael S. Tsirkin { 0x0301, "XGA controller"}, 1208315a1350SMichael S. Tsirkin { 0x0302, "3D controller"}, 1209315a1350SMichael S. Tsirkin { 0x0380, "Display controller"}, 1210315a1350SMichael S. Tsirkin { 0x0400, "Video controller", "video"}, 1211315a1350SMichael S. Tsirkin { 0x0401, "Audio controller", "sound"}, 1212315a1350SMichael S. Tsirkin { 0x0402, "Phone"}, 1213315a1350SMichael S. Tsirkin { 0x0403, "Audio controller", "sound"}, 1214315a1350SMichael S. Tsirkin { 0x0480, "Multimedia controller"}, 1215315a1350SMichael S. Tsirkin { 0x0500, "RAM controller", "memory"}, 1216315a1350SMichael S. Tsirkin { 0x0501, "Flash controller", "flash"}, 1217315a1350SMichael S. Tsirkin { 0x0580, "Memory controller"}, 1218315a1350SMichael S. Tsirkin { 0x0600, "Host bridge", "host"}, 1219315a1350SMichael S. Tsirkin { 0x0601, "ISA bridge", "isa"}, 1220315a1350SMichael S. Tsirkin { 0x0602, "EISA bridge", "eisa"}, 1221315a1350SMichael S. Tsirkin { 0x0603, "MC bridge", "mca"}, 1222315a1350SMichael S. Tsirkin { 0x0604, "PCI bridge", "pci"}, 1223315a1350SMichael S. Tsirkin { 0x0605, "PCMCIA bridge", "pcmcia"}, 1224315a1350SMichael S. Tsirkin { 0x0606, "NUBUS bridge", "nubus"}, 1225315a1350SMichael S. Tsirkin { 0x0607, "CARDBUS bridge", "cardbus"}, 1226315a1350SMichael S. Tsirkin { 0x0608, "RACEWAY bridge"}, 1227315a1350SMichael S. Tsirkin { 0x0680, "Bridge"}, 1228315a1350SMichael S. Tsirkin { 0x0700, "Serial port", "serial"}, 1229315a1350SMichael S. Tsirkin { 0x0701, "Parallel port", "parallel"}, 1230315a1350SMichael S. Tsirkin { 0x0800, "Interrupt controller", "interrupt-controller"}, 1231315a1350SMichael S. Tsirkin { 0x0801, "DMA controller", "dma-controller"}, 1232315a1350SMichael S. Tsirkin { 0x0802, "Timer", "timer"}, 1233315a1350SMichael S. Tsirkin { 0x0803, "RTC", "rtc"}, 1234315a1350SMichael S. Tsirkin { 0x0900, "Keyboard", "keyboard"}, 1235315a1350SMichael S. Tsirkin { 0x0901, "Pen", "pen"}, 1236315a1350SMichael S. Tsirkin { 0x0902, "Mouse", "mouse"}, 1237315a1350SMichael S. Tsirkin { 0x0A00, "Dock station", "dock", 0x00ff}, 1238315a1350SMichael S. Tsirkin { 0x0B00, "i386 cpu", "cpu", 0x00ff}, 1239315a1350SMichael S. Tsirkin { 0x0c00, "Fireware contorller", "fireware"}, 1240315a1350SMichael S. Tsirkin { 0x0c01, "Access bus controller", "access-bus"}, 1241315a1350SMichael S. Tsirkin { 0x0c02, "SSA controller", "ssa"}, 1242315a1350SMichael S. Tsirkin { 0x0c03, "USB controller", "usb"}, 1243315a1350SMichael S. Tsirkin { 0x0c04, "Fibre channel controller", "fibre-channel"}, 1244315a1350SMichael S. Tsirkin { 0x0c05, "SMBus"}, 1245315a1350SMichael S. Tsirkin { 0, NULL} 1246315a1350SMichael S. Tsirkin }; 1247315a1350SMichael S. Tsirkin 1248315a1350SMichael S. Tsirkin static void pci_for_each_device_under_bus(PCIBus *bus, 1249315a1350SMichael S. Tsirkin void (*fn)(PCIBus *b, PCIDevice *d, 1250315a1350SMichael S. Tsirkin void *opaque), 1251315a1350SMichael S. Tsirkin void *opaque) 1252315a1350SMichael S. Tsirkin { 1253315a1350SMichael S. Tsirkin PCIDevice *d; 1254315a1350SMichael S. Tsirkin int devfn; 1255315a1350SMichael S. Tsirkin 1256315a1350SMichael S. Tsirkin for(devfn = 0; devfn < ARRAY_SIZE(bus->devices); devfn++) { 1257315a1350SMichael S. Tsirkin d = bus->devices[devfn]; 1258315a1350SMichael S. Tsirkin if (d) { 1259315a1350SMichael S. Tsirkin fn(bus, d, opaque); 1260315a1350SMichael S. Tsirkin } 1261315a1350SMichael S. Tsirkin } 1262315a1350SMichael S. Tsirkin } 1263315a1350SMichael S. Tsirkin 1264315a1350SMichael S. Tsirkin void pci_for_each_device(PCIBus *bus, int bus_num, 1265315a1350SMichael S. Tsirkin void (*fn)(PCIBus *b, PCIDevice *d, void *opaque), 1266315a1350SMichael S. Tsirkin void *opaque) 1267315a1350SMichael S. Tsirkin { 1268315a1350SMichael S. Tsirkin bus = pci_find_bus_nr(bus, bus_num); 1269315a1350SMichael S. Tsirkin 1270315a1350SMichael S. Tsirkin if (bus) { 1271315a1350SMichael S. Tsirkin pci_for_each_device_under_bus(bus, fn, opaque); 1272315a1350SMichael S. Tsirkin } 1273315a1350SMichael S. Tsirkin } 1274315a1350SMichael S. Tsirkin 1275315a1350SMichael S. Tsirkin static const pci_class_desc *get_class_desc(int class) 1276315a1350SMichael S. Tsirkin { 1277315a1350SMichael S. Tsirkin const pci_class_desc *desc; 1278315a1350SMichael S. Tsirkin 1279315a1350SMichael S. Tsirkin desc = pci_class_descriptions; 1280315a1350SMichael S. Tsirkin while (desc->desc && class != desc->class) { 1281315a1350SMichael S. Tsirkin desc++; 1282315a1350SMichael S. Tsirkin } 1283315a1350SMichael S. Tsirkin 1284315a1350SMichael S. Tsirkin return desc; 1285315a1350SMichael S. Tsirkin } 1286315a1350SMichael S. Tsirkin 1287315a1350SMichael S. Tsirkin static PciDeviceInfoList *qmp_query_pci_devices(PCIBus *bus, int bus_num); 1288315a1350SMichael S. Tsirkin 1289315a1350SMichael S. Tsirkin static PciMemoryRegionList *qmp_query_pci_regions(const PCIDevice *dev) 1290315a1350SMichael S. Tsirkin { 1291315a1350SMichael S. Tsirkin PciMemoryRegionList *head = NULL, *cur_item = NULL; 1292315a1350SMichael S. Tsirkin int i; 1293315a1350SMichael S. Tsirkin 1294315a1350SMichael S. Tsirkin for (i = 0; i < PCI_NUM_REGIONS; i++) { 1295315a1350SMichael S. Tsirkin const PCIIORegion *r = &dev->io_regions[i]; 1296315a1350SMichael S. Tsirkin PciMemoryRegionList *region; 1297315a1350SMichael S. Tsirkin 1298315a1350SMichael S. Tsirkin if (!r->size) { 1299315a1350SMichael S. Tsirkin continue; 1300315a1350SMichael S. Tsirkin } 1301315a1350SMichael S. Tsirkin 1302315a1350SMichael S. Tsirkin region = g_malloc0(sizeof(*region)); 1303315a1350SMichael S. Tsirkin region->value = g_malloc0(sizeof(*region->value)); 1304315a1350SMichael S. Tsirkin 1305315a1350SMichael S. Tsirkin if (r->type & PCI_BASE_ADDRESS_SPACE_IO) { 1306315a1350SMichael S. Tsirkin region->value->type = g_strdup("io"); 1307315a1350SMichael S. Tsirkin } else { 1308315a1350SMichael S. Tsirkin region->value->type = g_strdup("memory"); 1309315a1350SMichael S. Tsirkin region->value->has_prefetch = true; 1310315a1350SMichael S. Tsirkin region->value->prefetch = !!(r->type & PCI_BASE_ADDRESS_MEM_PREFETCH); 1311315a1350SMichael S. Tsirkin region->value->has_mem_type_64 = true; 1312315a1350SMichael S. Tsirkin region->value->mem_type_64 = !!(r->type & PCI_BASE_ADDRESS_MEM_TYPE_64); 1313315a1350SMichael S. Tsirkin } 1314315a1350SMichael S. Tsirkin 1315315a1350SMichael S. Tsirkin region->value->bar = i; 1316315a1350SMichael S. Tsirkin region->value->address = r->addr; 1317315a1350SMichael S. Tsirkin region->value->size = r->size; 1318315a1350SMichael S. Tsirkin 1319315a1350SMichael S. Tsirkin /* XXX: waiting for the qapi to support GSList */ 1320315a1350SMichael S. Tsirkin if (!cur_item) { 1321315a1350SMichael S. Tsirkin head = cur_item = region; 1322315a1350SMichael S. Tsirkin } else { 1323315a1350SMichael S. Tsirkin cur_item->next = region; 1324315a1350SMichael S. Tsirkin cur_item = region; 1325315a1350SMichael S. Tsirkin } 1326315a1350SMichael S. Tsirkin } 1327315a1350SMichael S. Tsirkin 1328315a1350SMichael S. Tsirkin return head; 1329315a1350SMichael S. Tsirkin } 1330315a1350SMichael S. Tsirkin 1331315a1350SMichael S. Tsirkin static PciBridgeInfo *qmp_query_pci_bridge(PCIDevice *dev, PCIBus *bus, 1332315a1350SMichael S. Tsirkin int bus_num) 1333315a1350SMichael S. Tsirkin { 1334315a1350SMichael S. Tsirkin PciBridgeInfo *info; 1335315a1350SMichael S. Tsirkin 1336315a1350SMichael S. Tsirkin info = g_malloc0(sizeof(*info)); 1337315a1350SMichael S. Tsirkin 1338315a1350SMichael S. Tsirkin info->bus.number = dev->config[PCI_PRIMARY_BUS]; 1339315a1350SMichael S. Tsirkin info->bus.secondary = dev->config[PCI_SECONDARY_BUS]; 1340315a1350SMichael S. Tsirkin info->bus.subordinate = dev->config[PCI_SUBORDINATE_BUS]; 1341315a1350SMichael S. Tsirkin 1342315a1350SMichael S. Tsirkin info->bus.io_range = g_malloc0(sizeof(*info->bus.io_range)); 1343315a1350SMichael S. Tsirkin info->bus.io_range->base = pci_bridge_get_base(dev, PCI_BASE_ADDRESS_SPACE_IO); 1344315a1350SMichael S. Tsirkin info->bus.io_range->limit = pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_SPACE_IO); 1345315a1350SMichael S. Tsirkin 1346315a1350SMichael S. Tsirkin info->bus.memory_range = g_malloc0(sizeof(*info->bus.memory_range)); 1347315a1350SMichael S. Tsirkin info->bus.memory_range->base = pci_bridge_get_base(dev, PCI_BASE_ADDRESS_SPACE_MEMORY); 1348315a1350SMichael S. Tsirkin info->bus.memory_range->limit = pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_SPACE_MEMORY); 1349315a1350SMichael S. Tsirkin 1350315a1350SMichael S. Tsirkin info->bus.prefetchable_range = g_malloc0(sizeof(*info->bus.prefetchable_range)); 1351315a1350SMichael S. Tsirkin info->bus.prefetchable_range->base = pci_bridge_get_base(dev, PCI_BASE_ADDRESS_MEM_PREFETCH); 1352315a1350SMichael S. Tsirkin info->bus.prefetchable_range->limit = pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_MEM_PREFETCH); 1353315a1350SMichael S. Tsirkin 1354315a1350SMichael S. Tsirkin if (dev->config[PCI_SECONDARY_BUS] != 0) { 1355315a1350SMichael S. Tsirkin PCIBus *child_bus = pci_find_bus_nr(bus, dev->config[PCI_SECONDARY_BUS]); 1356315a1350SMichael S. Tsirkin if (child_bus) { 1357315a1350SMichael S. Tsirkin info->has_devices = true; 1358315a1350SMichael S. Tsirkin info->devices = qmp_query_pci_devices(child_bus, dev->config[PCI_SECONDARY_BUS]); 1359315a1350SMichael S. Tsirkin } 1360315a1350SMichael S. Tsirkin } 1361315a1350SMichael S. Tsirkin 1362315a1350SMichael S. Tsirkin return info; 1363315a1350SMichael S. Tsirkin } 1364315a1350SMichael S. Tsirkin 1365315a1350SMichael S. Tsirkin static PciDeviceInfo *qmp_query_pci_device(PCIDevice *dev, PCIBus *bus, 1366315a1350SMichael S. Tsirkin int bus_num) 1367315a1350SMichael S. Tsirkin { 1368315a1350SMichael S. Tsirkin const pci_class_desc *desc; 1369315a1350SMichael S. Tsirkin PciDeviceInfo *info; 1370315a1350SMichael S. Tsirkin uint8_t type; 1371315a1350SMichael S. Tsirkin int class; 1372315a1350SMichael S. Tsirkin 1373315a1350SMichael S. Tsirkin info = g_malloc0(sizeof(*info)); 1374315a1350SMichael S. Tsirkin info->bus = bus_num; 1375315a1350SMichael S. Tsirkin info->slot = PCI_SLOT(dev->devfn); 1376315a1350SMichael S. Tsirkin info->function = PCI_FUNC(dev->devfn); 1377315a1350SMichael S. Tsirkin 1378315a1350SMichael S. Tsirkin class = pci_get_word(dev->config + PCI_CLASS_DEVICE); 1379315a1350SMichael S. Tsirkin info->class_info.class = class; 1380315a1350SMichael S. Tsirkin desc = get_class_desc(class); 1381315a1350SMichael S. Tsirkin if (desc->desc) { 1382315a1350SMichael S. Tsirkin info->class_info.has_desc = true; 1383315a1350SMichael S. Tsirkin info->class_info.desc = g_strdup(desc->desc); 1384315a1350SMichael S. Tsirkin } 1385315a1350SMichael S. Tsirkin 1386315a1350SMichael S. Tsirkin info->id.vendor = pci_get_word(dev->config + PCI_VENDOR_ID); 1387315a1350SMichael S. Tsirkin info->id.device = pci_get_word(dev->config + PCI_DEVICE_ID); 1388315a1350SMichael S. Tsirkin info->regions = qmp_query_pci_regions(dev); 1389315a1350SMichael S. Tsirkin info->qdev_id = g_strdup(dev->qdev.id ? dev->qdev.id : ""); 1390315a1350SMichael S. Tsirkin 1391315a1350SMichael S. Tsirkin if (dev->config[PCI_INTERRUPT_PIN] != 0) { 1392315a1350SMichael S. Tsirkin info->has_irq = true; 1393315a1350SMichael S. Tsirkin info->irq = dev->config[PCI_INTERRUPT_LINE]; 1394315a1350SMichael S. Tsirkin } 1395315a1350SMichael S. Tsirkin 1396315a1350SMichael S. Tsirkin type = dev->config[PCI_HEADER_TYPE] & ~PCI_HEADER_TYPE_MULTI_FUNCTION; 1397315a1350SMichael S. Tsirkin if (type == PCI_HEADER_TYPE_BRIDGE) { 1398315a1350SMichael S. Tsirkin info->has_pci_bridge = true; 1399315a1350SMichael S. Tsirkin info->pci_bridge = qmp_query_pci_bridge(dev, bus, bus_num); 1400315a1350SMichael S. Tsirkin } 1401315a1350SMichael S. Tsirkin 1402315a1350SMichael S. Tsirkin return info; 1403315a1350SMichael S. Tsirkin } 1404315a1350SMichael S. Tsirkin 1405315a1350SMichael S. Tsirkin static PciDeviceInfoList *qmp_query_pci_devices(PCIBus *bus, int bus_num) 1406315a1350SMichael S. Tsirkin { 1407315a1350SMichael S. Tsirkin PciDeviceInfoList *info, *head = NULL, *cur_item = NULL; 1408315a1350SMichael S. Tsirkin PCIDevice *dev; 1409315a1350SMichael S. Tsirkin int devfn; 1410315a1350SMichael S. Tsirkin 1411315a1350SMichael S. Tsirkin for (devfn = 0; devfn < ARRAY_SIZE(bus->devices); devfn++) { 1412315a1350SMichael S. Tsirkin dev = bus->devices[devfn]; 1413315a1350SMichael S. Tsirkin if (dev) { 1414315a1350SMichael S. Tsirkin info = g_malloc0(sizeof(*info)); 1415315a1350SMichael S. Tsirkin info->value = qmp_query_pci_device(dev, bus, bus_num); 1416315a1350SMichael S. Tsirkin 1417315a1350SMichael S. Tsirkin /* XXX: waiting for the qapi to support GSList */ 1418315a1350SMichael S. Tsirkin if (!cur_item) { 1419315a1350SMichael S. Tsirkin head = cur_item = info; 1420315a1350SMichael S. Tsirkin } else { 1421315a1350SMichael S. Tsirkin cur_item->next = info; 1422315a1350SMichael S. Tsirkin cur_item = info; 1423315a1350SMichael S. Tsirkin } 1424315a1350SMichael S. Tsirkin } 1425315a1350SMichael S. Tsirkin } 1426315a1350SMichael S. Tsirkin 1427315a1350SMichael S. Tsirkin return head; 1428315a1350SMichael S. Tsirkin } 1429315a1350SMichael S. Tsirkin 1430315a1350SMichael S. Tsirkin static PciInfo *qmp_query_pci_bus(PCIBus *bus, int bus_num) 1431315a1350SMichael S. Tsirkin { 1432315a1350SMichael S. Tsirkin PciInfo *info = NULL; 1433315a1350SMichael S. Tsirkin 1434315a1350SMichael S. Tsirkin bus = pci_find_bus_nr(bus, bus_num); 1435315a1350SMichael S. Tsirkin if (bus) { 1436315a1350SMichael S. Tsirkin info = g_malloc0(sizeof(*info)); 1437315a1350SMichael S. Tsirkin info->bus = bus_num; 1438315a1350SMichael S. Tsirkin info->devices = qmp_query_pci_devices(bus, bus_num); 1439315a1350SMichael S. Tsirkin } 1440315a1350SMichael S. Tsirkin 1441315a1350SMichael S. Tsirkin return info; 1442315a1350SMichael S. Tsirkin } 1443315a1350SMichael S. Tsirkin 1444315a1350SMichael S. Tsirkin PciInfoList *qmp_query_pci(Error **errp) 1445315a1350SMichael S. Tsirkin { 1446315a1350SMichael S. Tsirkin PciInfoList *info, *head = NULL, *cur_item = NULL; 1447315a1350SMichael S. Tsirkin struct PCIHostBus *host; 1448315a1350SMichael S. Tsirkin 1449315a1350SMichael S. Tsirkin QLIST_FOREACH(host, &host_buses, next) { 1450315a1350SMichael S. Tsirkin info = g_malloc0(sizeof(*info)); 1451315a1350SMichael S. Tsirkin info->value = qmp_query_pci_bus(host->bus, 0); 1452315a1350SMichael S. Tsirkin 1453315a1350SMichael S. Tsirkin /* XXX: waiting for the qapi to support GSList */ 1454315a1350SMichael S. Tsirkin if (!cur_item) { 1455315a1350SMichael S. Tsirkin head = cur_item = info; 1456315a1350SMichael S. Tsirkin } else { 1457315a1350SMichael S. Tsirkin cur_item->next = info; 1458315a1350SMichael S. Tsirkin cur_item = info; 1459315a1350SMichael S. Tsirkin } 1460315a1350SMichael S. Tsirkin } 1461315a1350SMichael S. Tsirkin 1462315a1350SMichael S. Tsirkin return head; 1463315a1350SMichael S. Tsirkin } 1464315a1350SMichael S. Tsirkin 1465315a1350SMichael S. Tsirkin static const char * const pci_nic_models[] = { 1466315a1350SMichael S. Tsirkin "ne2k_pci", 1467315a1350SMichael S. Tsirkin "i82551", 1468315a1350SMichael S. Tsirkin "i82557b", 1469315a1350SMichael S. Tsirkin "i82559er", 1470315a1350SMichael S. Tsirkin "rtl8139", 1471315a1350SMichael S. Tsirkin "e1000", 1472315a1350SMichael S. Tsirkin "pcnet", 1473315a1350SMichael S. Tsirkin "virtio", 1474315a1350SMichael S. Tsirkin NULL 1475315a1350SMichael S. Tsirkin }; 1476315a1350SMichael S. Tsirkin 1477315a1350SMichael S. Tsirkin static const char * const pci_nic_names[] = { 1478315a1350SMichael S. Tsirkin "ne2k_pci", 1479315a1350SMichael S. Tsirkin "i82551", 1480315a1350SMichael S. Tsirkin "i82557b", 1481315a1350SMichael S. Tsirkin "i82559er", 1482315a1350SMichael S. Tsirkin "rtl8139", 1483315a1350SMichael S. Tsirkin "e1000", 1484315a1350SMichael S. Tsirkin "pcnet", 1485315a1350SMichael S. Tsirkin "virtio-net-pci", 1486315a1350SMichael S. Tsirkin NULL 1487315a1350SMichael S. Tsirkin }; 1488315a1350SMichael S. Tsirkin 1489315a1350SMichael S. Tsirkin /* Initialize a PCI NIC. */ 1490315a1350SMichael S. Tsirkin /* FIXME callers should check for failure, but don't */ 1491315a1350SMichael S. Tsirkin PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model, 1492315a1350SMichael S. Tsirkin const char *default_devaddr) 1493315a1350SMichael S. Tsirkin { 1494315a1350SMichael S. Tsirkin const char *devaddr = nd->devaddr ? nd->devaddr : default_devaddr; 1495315a1350SMichael S. Tsirkin PCIBus *bus; 1496315a1350SMichael S. Tsirkin int devfn; 1497315a1350SMichael S. Tsirkin PCIDevice *pci_dev; 1498315a1350SMichael S. Tsirkin DeviceState *dev; 1499315a1350SMichael S. Tsirkin int i; 1500315a1350SMichael S. Tsirkin 1501315a1350SMichael S. Tsirkin i = qemu_find_nic_model(nd, pci_nic_models, default_model); 1502315a1350SMichael S. Tsirkin if (i < 0) 1503315a1350SMichael S. Tsirkin return NULL; 1504315a1350SMichael S. Tsirkin 1505315a1350SMichael S. Tsirkin bus = pci_get_bus_devfn(&devfn, devaddr); 1506315a1350SMichael S. Tsirkin if (!bus) { 1507315a1350SMichael S. Tsirkin error_report("Invalid PCI device address %s for device %s", 1508315a1350SMichael S. Tsirkin devaddr, pci_nic_names[i]); 1509315a1350SMichael S. Tsirkin return NULL; 1510315a1350SMichael S. Tsirkin } 1511315a1350SMichael S. Tsirkin 1512315a1350SMichael S. Tsirkin pci_dev = pci_create(bus, devfn, pci_nic_names[i]); 1513315a1350SMichael S. Tsirkin dev = &pci_dev->qdev; 1514315a1350SMichael S. Tsirkin qdev_set_nic_properties(dev, nd); 1515315a1350SMichael S. Tsirkin if (qdev_init(dev) < 0) 1516315a1350SMichael S. Tsirkin return NULL; 1517315a1350SMichael S. Tsirkin return pci_dev; 1518315a1350SMichael S. Tsirkin } 1519315a1350SMichael S. Tsirkin 1520315a1350SMichael S. Tsirkin PCIDevice *pci_nic_init_nofail(NICInfo *nd, const char *default_model, 1521315a1350SMichael S. Tsirkin const char *default_devaddr) 1522315a1350SMichael S. Tsirkin { 1523315a1350SMichael S. Tsirkin PCIDevice *res; 1524315a1350SMichael S. Tsirkin 1525315a1350SMichael S. Tsirkin if (qemu_show_nic_models(nd->model, pci_nic_models)) 1526315a1350SMichael S. Tsirkin exit(0); 1527315a1350SMichael S. Tsirkin 1528315a1350SMichael S. Tsirkin res = pci_nic_init(nd, default_model, default_devaddr); 1529315a1350SMichael S. Tsirkin if (!res) 1530315a1350SMichael S. Tsirkin exit(1); 1531315a1350SMichael S. Tsirkin return res; 1532315a1350SMichael S. Tsirkin } 1533315a1350SMichael S. Tsirkin 1534315a1350SMichael S. Tsirkin PCIDevice *pci_vga_init(PCIBus *bus) 1535315a1350SMichael S. Tsirkin { 1536315a1350SMichael S. Tsirkin switch (vga_interface_type) { 1537315a1350SMichael S. Tsirkin case VGA_CIRRUS: 1538315a1350SMichael S. Tsirkin return pci_create_simple(bus, -1, "cirrus-vga"); 1539315a1350SMichael S. Tsirkin case VGA_QXL: 1540315a1350SMichael S. Tsirkin return pci_create_simple(bus, -1, "qxl-vga"); 1541315a1350SMichael S. Tsirkin case VGA_STD: 1542315a1350SMichael S. Tsirkin return pci_create_simple(bus, -1, "VGA"); 1543315a1350SMichael S. Tsirkin case VGA_VMWARE: 1544315a1350SMichael S. Tsirkin return pci_create_simple(bus, -1, "vmware-svga"); 1545315a1350SMichael S. Tsirkin case VGA_NONE: 1546315a1350SMichael S. Tsirkin default: /* Other non-PCI types. Checking for unsupported types is already 1547315a1350SMichael S. Tsirkin done in vl.c. */ 1548315a1350SMichael S. Tsirkin return NULL; 1549315a1350SMichael S. Tsirkin } 1550315a1350SMichael S. Tsirkin } 1551315a1350SMichael S. Tsirkin 1552315a1350SMichael S. Tsirkin /* Whether a given bus number is in range of the secondary 1553315a1350SMichael S. Tsirkin * bus of the given bridge device. */ 1554315a1350SMichael S. Tsirkin static bool pci_secondary_bus_in_range(PCIDevice *dev, int bus_num) 1555315a1350SMichael S. Tsirkin { 1556315a1350SMichael S. Tsirkin return !(pci_get_word(dev->config + PCI_BRIDGE_CONTROL) & 1557315a1350SMichael S. Tsirkin PCI_BRIDGE_CTL_BUS_RESET) /* Don't walk the bus if it's reset. */ && 1558315a1350SMichael S. Tsirkin dev->config[PCI_SECONDARY_BUS] < bus_num && 1559315a1350SMichael S. Tsirkin bus_num <= dev->config[PCI_SUBORDINATE_BUS]; 1560315a1350SMichael S. Tsirkin } 1561315a1350SMichael S. Tsirkin 1562315a1350SMichael S. Tsirkin static PCIBus *pci_find_bus_nr(PCIBus *bus, int bus_num) 1563315a1350SMichael S. Tsirkin { 1564315a1350SMichael S. Tsirkin PCIBus *sec; 1565315a1350SMichael S. Tsirkin 1566315a1350SMichael S. Tsirkin if (!bus) { 1567315a1350SMichael S. Tsirkin return NULL; 1568315a1350SMichael S. Tsirkin } 1569315a1350SMichael S. Tsirkin 1570315a1350SMichael S. Tsirkin if (pci_bus_num(bus) == bus_num) { 1571315a1350SMichael S. Tsirkin return bus; 1572315a1350SMichael S. Tsirkin } 1573315a1350SMichael S. Tsirkin 1574315a1350SMichael S. Tsirkin /* Consider all bus numbers in range for the host pci bridge. */ 1575315a1350SMichael S. Tsirkin if (bus->parent_dev && 1576315a1350SMichael S. Tsirkin !pci_secondary_bus_in_range(bus->parent_dev, bus_num)) { 1577315a1350SMichael S. Tsirkin return NULL; 1578315a1350SMichael S. Tsirkin } 1579315a1350SMichael S. Tsirkin 1580315a1350SMichael S. Tsirkin /* try child bus */ 1581315a1350SMichael S. Tsirkin for (; bus; bus = sec) { 1582315a1350SMichael S. Tsirkin QLIST_FOREACH(sec, &bus->child, sibling) { 1583315a1350SMichael S. Tsirkin assert(sec->parent_dev); 1584315a1350SMichael S. Tsirkin if (sec->parent_dev->config[PCI_SECONDARY_BUS] == bus_num) { 1585315a1350SMichael S. Tsirkin return sec; 1586315a1350SMichael S. Tsirkin } 1587315a1350SMichael S. Tsirkin if (pci_secondary_bus_in_range(sec->parent_dev, bus_num)) { 1588315a1350SMichael S. Tsirkin break; 1589315a1350SMichael S. Tsirkin } 1590315a1350SMichael S. Tsirkin } 1591315a1350SMichael S. Tsirkin } 1592315a1350SMichael S. Tsirkin 1593315a1350SMichael S. Tsirkin return NULL; 1594315a1350SMichael S. Tsirkin } 1595315a1350SMichael S. Tsirkin 1596315a1350SMichael S. Tsirkin PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn) 1597315a1350SMichael S. Tsirkin { 1598315a1350SMichael S. Tsirkin bus = pci_find_bus_nr(bus, bus_num); 1599315a1350SMichael S. Tsirkin 1600315a1350SMichael S. Tsirkin if (!bus) 1601315a1350SMichael S. Tsirkin return NULL; 1602315a1350SMichael S. Tsirkin 1603315a1350SMichael S. Tsirkin return bus->devices[devfn]; 1604315a1350SMichael S. Tsirkin } 1605315a1350SMichael S. Tsirkin 1606315a1350SMichael S. Tsirkin static int pci_qdev_init(DeviceState *qdev) 1607315a1350SMichael S. Tsirkin { 1608315a1350SMichael S. Tsirkin PCIDevice *pci_dev = (PCIDevice *)qdev; 1609315a1350SMichael S. Tsirkin PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev); 1610315a1350SMichael S. Tsirkin PCIBus *bus; 1611315a1350SMichael S. Tsirkin int rc; 1612315a1350SMichael S. Tsirkin bool is_default_rom; 1613315a1350SMichael S. Tsirkin 1614315a1350SMichael S. Tsirkin /* initialize cap_present for pci_is_express() and pci_config_size() */ 1615315a1350SMichael S. Tsirkin if (pc->is_express) { 1616315a1350SMichael S. Tsirkin pci_dev->cap_present |= QEMU_PCI_CAP_EXPRESS; 1617315a1350SMichael S. Tsirkin } 1618315a1350SMichael S. Tsirkin 1619315a1350SMichael S. Tsirkin bus = FROM_QBUS(PCIBus, qdev_get_parent_bus(qdev)); 1620315a1350SMichael S. Tsirkin pci_dev = do_pci_register_device(pci_dev, bus, 1621315a1350SMichael S. Tsirkin object_get_typename(OBJECT(qdev)), 1622315a1350SMichael S. Tsirkin pci_dev->devfn); 1623315a1350SMichael S. Tsirkin if (pci_dev == NULL) 1624315a1350SMichael S. Tsirkin return -1; 1625315a1350SMichael S. Tsirkin if (qdev->hotplugged && pc->no_hotplug) { 1626315a1350SMichael S. Tsirkin qerror_report(QERR_DEVICE_NO_HOTPLUG, object_get_typename(OBJECT(pci_dev))); 1627315a1350SMichael S. Tsirkin do_pci_unregister_device(pci_dev); 1628315a1350SMichael S. Tsirkin return -1; 1629315a1350SMichael S. Tsirkin } 1630315a1350SMichael S. Tsirkin if (pc->init) { 1631315a1350SMichael S. Tsirkin rc = pc->init(pci_dev); 1632315a1350SMichael S. Tsirkin if (rc != 0) { 1633315a1350SMichael S. Tsirkin do_pci_unregister_device(pci_dev); 1634315a1350SMichael S. Tsirkin return rc; 1635315a1350SMichael S. Tsirkin } 1636315a1350SMichael S. Tsirkin } 1637315a1350SMichael S. Tsirkin 1638315a1350SMichael S. Tsirkin /* rom loading */ 1639315a1350SMichael S. Tsirkin is_default_rom = false; 1640315a1350SMichael S. Tsirkin if (pci_dev->romfile == NULL && pc->romfile != NULL) { 1641315a1350SMichael S. Tsirkin pci_dev->romfile = g_strdup(pc->romfile); 1642315a1350SMichael S. Tsirkin is_default_rom = true; 1643315a1350SMichael S. Tsirkin } 1644315a1350SMichael S. Tsirkin pci_add_option_rom(pci_dev, is_default_rom); 1645315a1350SMichael S. Tsirkin 1646315a1350SMichael S. Tsirkin if (bus->hotplug) { 1647315a1350SMichael S. Tsirkin /* Let buses differentiate between hotplug and when device is 1648315a1350SMichael S. Tsirkin * enabled during qemu machine creation. */ 1649315a1350SMichael S. Tsirkin rc = bus->hotplug(bus->hotplug_qdev, pci_dev, 1650315a1350SMichael S. Tsirkin qdev->hotplugged ? PCI_HOTPLUG_ENABLED: 1651315a1350SMichael S. Tsirkin PCI_COLDPLUG_ENABLED); 1652315a1350SMichael S. Tsirkin if (rc != 0) { 1653315a1350SMichael S. Tsirkin int r = pci_unregister_device(&pci_dev->qdev); 1654315a1350SMichael S. Tsirkin assert(!r); 1655315a1350SMichael S. Tsirkin return rc; 1656315a1350SMichael S. Tsirkin } 1657315a1350SMichael S. Tsirkin } 1658315a1350SMichael S. Tsirkin return 0; 1659315a1350SMichael S. Tsirkin } 1660315a1350SMichael S. Tsirkin 1661315a1350SMichael S. Tsirkin static int pci_unplug_device(DeviceState *qdev) 1662315a1350SMichael S. Tsirkin { 1663315a1350SMichael S. Tsirkin PCIDevice *dev = PCI_DEVICE(qdev); 1664315a1350SMichael S. Tsirkin PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev); 1665315a1350SMichael S. Tsirkin 1666315a1350SMichael S. Tsirkin if (pc->no_hotplug) { 1667315a1350SMichael S. Tsirkin qerror_report(QERR_DEVICE_NO_HOTPLUG, object_get_typename(OBJECT(dev))); 1668315a1350SMichael S. Tsirkin return -1; 1669315a1350SMichael S. Tsirkin } 1670315a1350SMichael S. Tsirkin return dev->bus->hotplug(dev->bus->hotplug_qdev, dev, 1671315a1350SMichael S. Tsirkin PCI_HOTPLUG_DISABLED); 1672315a1350SMichael S. Tsirkin } 1673315a1350SMichael S. Tsirkin 1674315a1350SMichael S. Tsirkin PCIDevice *pci_create_multifunction(PCIBus *bus, int devfn, bool multifunction, 1675315a1350SMichael S. Tsirkin const char *name) 1676315a1350SMichael S. Tsirkin { 1677315a1350SMichael S. Tsirkin DeviceState *dev; 1678315a1350SMichael S. Tsirkin 1679315a1350SMichael S. Tsirkin dev = qdev_create(&bus->qbus, name); 1680315a1350SMichael S. Tsirkin qdev_prop_set_int32(dev, "addr", devfn); 1681315a1350SMichael S. Tsirkin qdev_prop_set_bit(dev, "multifunction", multifunction); 1682315a1350SMichael S. Tsirkin return PCI_DEVICE(dev); 1683315a1350SMichael S. Tsirkin } 1684315a1350SMichael S. Tsirkin 1685315a1350SMichael S. Tsirkin PCIDevice *pci_create_simple_multifunction(PCIBus *bus, int devfn, 1686315a1350SMichael S. Tsirkin bool multifunction, 1687315a1350SMichael S. Tsirkin const char *name) 1688315a1350SMichael S. Tsirkin { 1689315a1350SMichael S. Tsirkin PCIDevice *dev = pci_create_multifunction(bus, devfn, multifunction, name); 1690315a1350SMichael S. Tsirkin qdev_init_nofail(&dev->qdev); 1691315a1350SMichael S. Tsirkin return dev; 1692315a1350SMichael S. Tsirkin } 1693315a1350SMichael S. Tsirkin 1694315a1350SMichael S. Tsirkin PCIDevice *pci_create(PCIBus *bus, int devfn, const char *name) 1695315a1350SMichael S. Tsirkin { 1696315a1350SMichael S. Tsirkin return pci_create_multifunction(bus, devfn, false, name); 1697315a1350SMichael S. Tsirkin } 1698315a1350SMichael S. Tsirkin 1699315a1350SMichael S. Tsirkin PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name) 1700315a1350SMichael S. Tsirkin { 1701315a1350SMichael S. Tsirkin return pci_create_simple_multifunction(bus, devfn, false, name); 1702315a1350SMichael S. Tsirkin } 1703315a1350SMichael S. Tsirkin 1704315a1350SMichael S. Tsirkin static uint8_t pci_find_space(PCIDevice *pdev, uint8_t size) 1705315a1350SMichael S. Tsirkin { 1706315a1350SMichael S. Tsirkin int offset = PCI_CONFIG_HEADER_SIZE; 1707315a1350SMichael S. Tsirkin int i; 1708315a1350SMichael S. Tsirkin for (i = PCI_CONFIG_HEADER_SIZE; i < PCI_CONFIG_SPACE_SIZE; ++i) { 1709315a1350SMichael S. Tsirkin if (pdev->used[i]) 1710315a1350SMichael S. Tsirkin offset = i + 1; 1711315a1350SMichael S. Tsirkin else if (i - offset + 1 == size) 1712315a1350SMichael S. Tsirkin return offset; 1713315a1350SMichael S. Tsirkin } 1714315a1350SMichael S. Tsirkin return 0; 1715315a1350SMichael S. Tsirkin } 1716315a1350SMichael S. Tsirkin 1717315a1350SMichael S. Tsirkin static uint8_t pci_find_capability_list(PCIDevice *pdev, uint8_t cap_id, 1718315a1350SMichael S. Tsirkin uint8_t *prev_p) 1719315a1350SMichael S. Tsirkin { 1720315a1350SMichael S. Tsirkin uint8_t next, prev; 1721315a1350SMichael S. Tsirkin 1722315a1350SMichael S. Tsirkin if (!(pdev->config[PCI_STATUS] & PCI_STATUS_CAP_LIST)) 1723315a1350SMichael S. Tsirkin return 0; 1724315a1350SMichael S. Tsirkin 1725315a1350SMichael S. Tsirkin for (prev = PCI_CAPABILITY_LIST; (next = pdev->config[prev]); 1726315a1350SMichael S. Tsirkin prev = next + PCI_CAP_LIST_NEXT) 1727315a1350SMichael S. Tsirkin if (pdev->config[next + PCI_CAP_LIST_ID] == cap_id) 1728315a1350SMichael S. Tsirkin break; 1729315a1350SMichael S. Tsirkin 1730315a1350SMichael S. Tsirkin if (prev_p) 1731315a1350SMichael S. Tsirkin *prev_p = prev; 1732315a1350SMichael S. Tsirkin return next; 1733315a1350SMichael S. Tsirkin } 1734315a1350SMichael S. Tsirkin 1735315a1350SMichael S. Tsirkin static uint8_t pci_find_capability_at_offset(PCIDevice *pdev, uint8_t offset) 1736315a1350SMichael S. Tsirkin { 1737315a1350SMichael S. Tsirkin uint8_t next, prev, found = 0; 1738315a1350SMichael S. Tsirkin 1739315a1350SMichael S. Tsirkin if (!(pdev->used[offset])) { 1740315a1350SMichael S. Tsirkin return 0; 1741315a1350SMichael S. Tsirkin } 1742315a1350SMichael S. Tsirkin 1743315a1350SMichael S. Tsirkin assert(pdev->config[PCI_STATUS] & PCI_STATUS_CAP_LIST); 1744315a1350SMichael S. Tsirkin 1745315a1350SMichael S. Tsirkin for (prev = PCI_CAPABILITY_LIST; (next = pdev->config[prev]); 1746315a1350SMichael S. Tsirkin prev = next + PCI_CAP_LIST_NEXT) { 1747315a1350SMichael S. Tsirkin if (next <= offset && next > found) { 1748315a1350SMichael S. Tsirkin found = next; 1749315a1350SMichael S. Tsirkin } 1750315a1350SMichael S. Tsirkin } 1751315a1350SMichael S. Tsirkin return found; 1752315a1350SMichael S. Tsirkin } 1753315a1350SMichael S. Tsirkin 1754315a1350SMichael S. Tsirkin /* Patch the PCI vendor and device ids in a PCI rom image if necessary. 1755315a1350SMichael S. Tsirkin This is needed for an option rom which is used for more than one device. */ 1756315a1350SMichael S. Tsirkin static void pci_patch_ids(PCIDevice *pdev, uint8_t *ptr, int size) 1757315a1350SMichael S. Tsirkin { 1758315a1350SMichael S. Tsirkin uint16_t vendor_id; 1759315a1350SMichael S. Tsirkin uint16_t device_id; 1760315a1350SMichael S. Tsirkin uint16_t rom_vendor_id; 1761315a1350SMichael S. Tsirkin uint16_t rom_device_id; 1762315a1350SMichael S. Tsirkin uint16_t rom_magic; 1763315a1350SMichael S. Tsirkin uint16_t pcir_offset; 1764315a1350SMichael S. Tsirkin uint8_t checksum; 1765315a1350SMichael S. Tsirkin 1766315a1350SMichael S. Tsirkin /* Words in rom data are little endian (like in PCI configuration), 1767315a1350SMichael S. Tsirkin so they can be read / written with pci_get_word / pci_set_word. */ 1768315a1350SMichael S. Tsirkin 1769315a1350SMichael S. Tsirkin /* Only a valid rom will be patched. */ 1770315a1350SMichael S. Tsirkin rom_magic = pci_get_word(ptr); 1771315a1350SMichael S. Tsirkin if (rom_magic != 0xaa55) { 1772315a1350SMichael S. Tsirkin PCI_DPRINTF("Bad ROM magic %04x\n", rom_magic); 1773315a1350SMichael S. Tsirkin return; 1774315a1350SMichael S. Tsirkin } 1775315a1350SMichael S. Tsirkin pcir_offset = pci_get_word(ptr + 0x18); 1776315a1350SMichael S. Tsirkin if (pcir_offset + 8 >= size || memcmp(ptr + pcir_offset, "PCIR", 4)) { 1777315a1350SMichael S. Tsirkin PCI_DPRINTF("Bad PCIR offset 0x%x or signature\n", pcir_offset); 1778315a1350SMichael S. Tsirkin return; 1779315a1350SMichael S. Tsirkin } 1780315a1350SMichael S. Tsirkin 1781315a1350SMichael S. Tsirkin vendor_id = pci_get_word(pdev->config + PCI_VENDOR_ID); 1782315a1350SMichael S. Tsirkin device_id = pci_get_word(pdev->config + PCI_DEVICE_ID); 1783315a1350SMichael S. Tsirkin rom_vendor_id = pci_get_word(ptr + pcir_offset + 4); 1784315a1350SMichael S. Tsirkin rom_device_id = pci_get_word(ptr + pcir_offset + 6); 1785315a1350SMichael S. Tsirkin 1786315a1350SMichael S. Tsirkin PCI_DPRINTF("%s: ROM id %04x%04x / PCI id %04x%04x\n", pdev->romfile, 1787315a1350SMichael S. Tsirkin vendor_id, device_id, rom_vendor_id, rom_device_id); 1788315a1350SMichael S. Tsirkin 1789315a1350SMichael S. Tsirkin checksum = ptr[6]; 1790315a1350SMichael S. Tsirkin 1791315a1350SMichael S. Tsirkin if (vendor_id != rom_vendor_id) { 1792315a1350SMichael S. Tsirkin /* Patch vendor id and checksum (at offset 6 for etherboot roms). */ 1793315a1350SMichael S. Tsirkin checksum += (uint8_t)rom_vendor_id + (uint8_t)(rom_vendor_id >> 8); 1794315a1350SMichael S. Tsirkin checksum -= (uint8_t)vendor_id + (uint8_t)(vendor_id >> 8); 1795315a1350SMichael S. Tsirkin PCI_DPRINTF("ROM checksum %02x / %02x\n", ptr[6], checksum); 1796315a1350SMichael S. Tsirkin ptr[6] = checksum; 1797315a1350SMichael S. Tsirkin pci_set_word(ptr + pcir_offset + 4, vendor_id); 1798315a1350SMichael S. Tsirkin } 1799315a1350SMichael S. Tsirkin 1800315a1350SMichael S. Tsirkin if (device_id != rom_device_id) { 1801315a1350SMichael S. Tsirkin /* Patch device id and checksum (at offset 6 for etherboot roms). */ 1802315a1350SMichael S. Tsirkin checksum += (uint8_t)rom_device_id + (uint8_t)(rom_device_id >> 8); 1803315a1350SMichael S. Tsirkin checksum -= (uint8_t)device_id + (uint8_t)(device_id >> 8); 1804315a1350SMichael S. Tsirkin PCI_DPRINTF("ROM checksum %02x / %02x\n", ptr[6], checksum); 1805315a1350SMichael S. Tsirkin ptr[6] = checksum; 1806315a1350SMichael S. Tsirkin pci_set_word(ptr + pcir_offset + 6, device_id); 1807315a1350SMichael S. Tsirkin } 1808315a1350SMichael S. Tsirkin } 1809315a1350SMichael S. Tsirkin 1810315a1350SMichael S. Tsirkin /* Add an option rom for the device */ 1811315a1350SMichael S. Tsirkin static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom) 1812315a1350SMichael S. Tsirkin { 1813315a1350SMichael S. Tsirkin int size; 1814315a1350SMichael S. Tsirkin char *path; 1815315a1350SMichael S. Tsirkin void *ptr; 1816315a1350SMichael S. Tsirkin char name[32]; 1817315a1350SMichael S. Tsirkin const VMStateDescription *vmsd; 1818315a1350SMichael S. Tsirkin 1819315a1350SMichael S. Tsirkin if (!pdev->romfile) 1820315a1350SMichael S. Tsirkin return 0; 1821315a1350SMichael S. Tsirkin if (strlen(pdev->romfile) == 0) 1822315a1350SMichael S. Tsirkin return 0; 1823315a1350SMichael S. Tsirkin 1824315a1350SMichael S. Tsirkin if (!pdev->rom_bar) { 1825315a1350SMichael S. Tsirkin /* 1826315a1350SMichael S. Tsirkin * Load rom via fw_cfg instead of creating a rom bar, 1827315a1350SMichael S. Tsirkin * for 0.11 compatibility. 1828315a1350SMichael S. Tsirkin */ 1829315a1350SMichael S. Tsirkin int class = pci_get_word(pdev->config + PCI_CLASS_DEVICE); 1830315a1350SMichael S. Tsirkin if (class == 0x0300) { 1831315a1350SMichael S. Tsirkin rom_add_vga(pdev->romfile); 1832315a1350SMichael S. Tsirkin } else { 1833315a1350SMichael S. Tsirkin rom_add_option(pdev->romfile, -1); 1834315a1350SMichael S. Tsirkin } 1835315a1350SMichael S. Tsirkin return 0; 1836315a1350SMichael S. Tsirkin } 1837315a1350SMichael S. Tsirkin 1838315a1350SMichael S. Tsirkin path = qemu_find_file(QEMU_FILE_TYPE_BIOS, pdev->romfile); 1839315a1350SMichael S. Tsirkin if (path == NULL) { 1840315a1350SMichael S. Tsirkin path = g_strdup(pdev->romfile); 1841315a1350SMichael S. Tsirkin } 1842315a1350SMichael S. Tsirkin 1843315a1350SMichael S. Tsirkin size = get_image_size(path); 1844315a1350SMichael S. Tsirkin if (size < 0) { 1845315a1350SMichael S. Tsirkin error_report("%s: failed to find romfile \"%s\"", 1846315a1350SMichael S. Tsirkin __FUNCTION__, pdev->romfile); 1847315a1350SMichael S. Tsirkin g_free(path); 1848315a1350SMichael S. Tsirkin return -1; 1849315a1350SMichael S. Tsirkin } 1850315a1350SMichael S. Tsirkin if (size & (size - 1)) { 1851315a1350SMichael S. Tsirkin size = 1 << qemu_fls(size); 1852315a1350SMichael S. Tsirkin } 1853315a1350SMichael S. Tsirkin 1854315a1350SMichael S. Tsirkin vmsd = qdev_get_vmsd(DEVICE(pdev)); 1855315a1350SMichael S. Tsirkin 1856315a1350SMichael S. Tsirkin if (vmsd) { 1857315a1350SMichael S. Tsirkin snprintf(name, sizeof(name), "%s.rom", vmsd->name); 1858315a1350SMichael S. Tsirkin } else { 1859315a1350SMichael S. Tsirkin snprintf(name, sizeof(name), "%s.rom", object_get_typename(OBJECT(pdev))); 1860315a1350SMichael S. Tsirkin } 1861315a1350SMichael S. Tsirkin pdev->has_rom = true; 1862315a1350SMichael S. Tsirkin memory_region_init_ram(&pdev->rom, name, size); 1863315a1350SMichael S. Tsirkin vmstate_register_ram(&pdev->rom, &pdev->qdev); 1864315a1350SMichael S. Tsirkin ptr = memory_region_get_ram_ptr(&pdev->rom); 1865315a1350SMichael S. Tsirkin load_image(path, ptr); 1866315a1350SMichael S. Tsirkin g_free(path); 1867315a1350SMichael S. Tsirkin 1868315a1350SMichael S. Tsirkin if (is_default_rom) { 1869315a1350SMichael S. Tsirkin /* Only the default rom images will be patched (if needed). */ 1870315a1350SMichael S. Tsirkin pci_patch_ids(pdev, ptr, size); 1871315a1350SMichael S. Tsirkin } 1872315a1350SMichael S. Tsirkin 1873315a1350SMichael S. Tsirkin qemu_put_ram_ptr(ptr); 1874315a1350SMichael S. Tsirkin 1875315a1350SMichael S. Tsirkin pci_register_bar(pdev, PCI_ROM_SLOT, 0, &pdev->rom); 1876315a1350SMichael S. Tsirkin 1877315a1350SMichael S. Tsirkin return 0; 1878315a1350SMichael S. Tsirkin } 1879315a1350SMichael S. Tsirkin 1880315a1350SMichael S. Tsirkin static void pci_del_option_rom(PCIDevice *pdev) 1881315a1350SMichael S. Tsirkin { 1882315a1350SMichael S. Tsirkin if (!pdev->has_rom) 1883315a1350SMichael S. Tsirkin return; 1884315a1350SMichael S. Tsirkin 1885315a1350SMichael S. Tsirkin vmstate_unregister_ram(&pdev->rom, &pdev->qdev); 1886315a1350SMichael S. Tsirkin memory_region_destroy(&pdev->rom); 1887315a1350SMichael S. Tsirkin pdev->has_rom = false; 1888315a1350SMichael S. Tsirkin } 1889315a1350SMichael S. Tsirkin 1890315a1350SMichael S. Tsirkin /* 1891315a1350SMichael S. Tsirkin * if !offset 1892315a1350SMichael S. Tsirkin * Reserve space and add capability to the linked list in pci config space 1893315a1350SMichael S. Tsirkin * 1894315a1350SMichael S. Tsirkin * if offset = 0, 1895315a1350SMichael S. Tsirkin * Find and reserve space and add capability to the linked list 1896315a1350SMichael S. Tsirkin * in pci config space */ 1897315a1350SMichael S. Tsirkin int pci_add_capability(PCIDevice *pdev, uint8_t cap_id, 1898315a1350SMichael S. Tsirkin uint8_t offset, uint8_t size) 1899315a1350SMichael S. Tsirkin { 1900315a1350SMichael S. Tsirkin uint8_t *config; 1901315a1350SMichael S. Tsirkin int i, overlapping_cap; 1902315a1350SMichael S. Tsirkin 1903315a1350SMichael S. Tsirkin if (!offset) { 1904315a1350SMichael S. Tsirkin offset = pci_find_space(pdev, size); 1905315a1350SMichael S. Tsirkin if (!offset) { 1906315a1350SMichael S. Tsirkin return -ENOSPC; 1907315a1350SMichael S. Tsirkin } 1908315a1350SMichael S. Tsirkin } else { 1909315a1350SMichael S. Tsirkin /* Verify that capabilities don't overlap. Note: device assignment 1910315a1350SMichael S. Tsirkin * depends on this check to verify that the device is not broken. 1911315a1350SMichael S. Tsirkin * Should never trigger for emulated devices, but it's helpful 1912315a1350SMichael S. Tsirkin * for debugging these. */ 1913315a1350SMichael S. Tsirkin for (i = offset; i < offset + size; i++) { 1914315a1350SMichael S. Tsirkin overlapping_cap = pci_find_capability_at_offset(pdev, i); 1915315a1350SMichael S. Tsirkin if (overlapping_cap) { 1916315a1350SMichael S. Tsirkin fprintf(stderr, "ERROR: %04x:%02x:%02x.%x " 1917315a1350SMichael S. Tsirkin "Attempt to add PCI capability %x at offset " 1918315a1350SMichael S. Tsirkin "%x overlaps existing capability %x at offset %x\n", 1919315a1350SMichael S. Tsirkin pci_find_domain(pdev->bus), pci_bus_num(pdev->bus), 1920315a1350SMichael S. Tsirkin PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), 1921315a1350SMichael S. Tsirkin cap_id, offset, overlapping_cap, i); 1922315a1350SMichael S. Tsirkin return -EINVAL; 1923315a1350SMichael S. Tsirkin } 1924315a1350SMichael S. Tsirkin } 1925315a1350SMichael S. Tsirkin } 1926315a1350SMichael S. Tsirkin 1927315a1350SMichael S. Tsirkin config = pdev->config + offset; 1928315a1350SMichael S. Tsirkin config[PCI_CAP_LIST_ID] = cap_id; 1929315a1350SMichael S. Tsirkin config[PCI_CAP_LIST_NEXT] = pdev->config[PCI_CAPABILITY_LIST]; 1930315a1350SMichael S. Tsirkin pdev->config[PCI_CAPABILITY_LIST] = offset; 1931315a1350SMichael S. Tsirkin pdev->config[PCI_STATUS] |= PCI_STATUS_CAP_LIST; 1932315a1350SMichael S. Tsirkin memset(pdev->used + offset, 0xFF, QEMU_ALIGN_UP(size, 4)); 1933315a1350SMichael S. Tsirkin /* Make capability read-only by default */ 1934315a1350SMichael S. Tsirkin memset(pdev->wmask + offset, 0, size); 1935315a1350SMichael S. Tsirkin /* Check capability by default */ 1936315a1350SMichael S. Tsirkin memset(pdev->cmask + offset, 0xFF, size); 1937315a1350SMichael S. Tsirkin return offset; 1938315a1350SMichael S. Tsirkin } 1939315a1350SMichael S. Tsirkin 1940315a1350SMichael S. Tsirkin /* Unlink capability from the pci config space. */ 1941315a1350SMichael S. Tsirkin void pci_del_capability(PCIDevice *pdev, uint8_t cap_id, uint8_t size) 1942315a1350SMichael S. Tsirkin { 1943315a1350SMichael S. Tsirkin uint8_t prev, offset = pci_find_capability_list(pdev, cap_id, &prev); 1944315a1350SMichael S. Tsirkin if (!offset) 1945315a1350SMichael S. Tsirkin return; 1946315a1350SMichael S. Tsirkin pdev->config[prev] = pdev->config[offset + PCI_CAP_LIST_NEXT]; 1947315a1350SMichael S. Tsirkin /* Make capability writable again */ 1948315a1350SMichael S. Tsirkin memset(pdev->wmask + offset, 0xff, size); 1949315a1350SMichael S. Tsirkin memset(pdev->w1cmask + offset, 0, size); 1950315a1350SMichael S. Tsirkin /* Clear cmask as device-specific registers can't be checked */ 1951315a1350SMichael S. Tsirkin memset(pdev->cmask + offset, 0, size); 1952315a1350SMichael S. Tsirkin memset(pdev->used + offset, 0, QEMU_ALIGN_UP(size, 4)); 1953315a1350SMichael S. Tsirkin 1954315a1350SMichael S. Tsirkin if (!pdev->config[PCI_CAPABILITY_LIST]) 1955315a1350SMichael S. Tsirkin pdev->config[PCI_STATUS] &= ~PCI_STATUS_CAP_LIST; 1956315a1350SMichael S. Tsirkin } 1957315a1350SMichael S. Tsirkin 1958315a1350SMichael S. Tsirkin uint8_t pci_find_capability(PCIDevice *pdev, uint8_t cap_id) 1959315a1350SMichael S. Tsirkin { 1960315a1350SMichael S. Tsirkin return pci_find_capability_list(pdev, cap_id, NULL); 1961315a1350SMichael S. Tsirkin } 1962315a1350SMichael S. Tsirkin 1963315a1350SMichael S. Tsirkin static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent) 1964315a1350SMichael S. Tsirkin { 1965315a1350SMichael S. Tsirkin PCIDevice *d = (PCIDevice *)dev; 1966315a1350SMichael S. Tsirkin const pci_class_desc *desc; 1967315a1350SMichael S. Tsirkin char ctxt[64]; 1968315a1350SMichael S. Tsirkin PCIIORegion *r; 1969315a1350SMichael S. Tsirkin int i, class; 1970315a1350SMichael S. Tsirkin 1971315a1350SMichael S. Tsirkin class = pci_get_word(d->config + PCI_CLASS_DEVICE); 1972315a1350SMichael S. Tsirkin desc = pci_class_descriptions; 1973315a1350SMichael S. Tsirkin while (desc->desc && class != desc->class) 1974315a1350SMichael S. Tsirkin desc++; 1975315a1350SMichael S. Tsirkin if (desc->desc) { 1976315a1350SMichael S. Tsirkin snprintf(ctxt, sizeof(ctxt), "%s", desc->desc); 1977315a1350SMichael S. Tsirkin } else { 1978315a1350SMichael S. Tsirkin snprintf(ctxt, sizeof(ctxt), "Class %04x", class); 1979315a1350SMichael S. Tsirkin } 1980315a1350SMichael S. Tsirkin 1981315a1350SMichael S. Tsirkin monitor_printf(mon, "%*sclass %s, addr %02x:%02x.%x, " 1982315a1350SMichael S. Tsirkin "pci id %04x:%04x (sub %04x:%04x)\n", 1983315a1350SMichael S. Tsirkin indent, "", ctxt, pci_bus_num(d->bus), 1984315a1350SMichael S. Tsirkin PCI_SLOT(d->devfn), PCI_FUNC(d->devfn), 1985315a1350SMichael S. Tsirkin pci_get_word(d->config + PCI_VENDOR_ID), 1986315a1350SMichael S. Tsirkin pci_get_word(d->config + PCI_DEVICE_ID), 1987315a1350SMichael S. Tsirkin pci_get_word(d->config + PCI_SUBSYSTEM_VENDOR_ID), 1988315a1350SMichael S. Tsirkin pci_get_word(d->config + PCI_SUBSYSTEM_ID)); 1989315a1350SMichael S. Tsirkin for (i = 0; i < PCI_NUM_REGIONS; i++) { 1990315a1350SMichael S. Tsirkin r = &d->io_regions[i]; 1991315a1350SMichael S. Tsirkin if (!r->size) 1992315a1350SMichael S. Tsirkin continue; 1993315a1350SMichael S. Tsirkin monitor_printf(mon, "%*sbar %d: %s at 0x%"FMT_PCIBUS 1994315a1350SMichael S. Tsirkin " [0x%"FMT_PCIBUS"]\n", 1995315a1350SMichael S. Tsirkin indent, "", 1996315a1350SMichael S. Tsirkin i, r->type & PCI_BASE_ADDRESS_SPACE_IO ? "i/o" : "mem", 1997315a1350SMichael S. Tsirkin r->addr, r->addr + r->size - 1); 1998315a1350SMichael S. Tsirkin } 1999315a1350SMichael S. Tsirkin } 2000315a1350SMichael S. Tsirkin 2001315a1350SMichael S. Tsirkin static char *pci_dev_fw_name(DeviceState *dev, char *buf, int len) 2002315a1350SMichael S. Tsirkin { 2003315a1350SMichael S. Tsirkin PCIDevice *d = (PCIDevice *)dev; 2004315a1350SMichael S. Tsirkin const char *name = NULL; 2005315a1350SMichael S. Tsirkin const pci_class_desc *desc = pci_class_descriptions; 2006315a1350SMichael S. Tsirkin int class = pci_get_word(d->config + PCI_CLASS_DEVICE); 2007315a1350SMichael S. Tsirkin 2008315a1350SMichael S. Tsirkin while (desc->desc && 2009315a1350SMichael S. Tsirkin (class & ~desc->fw_ign_bits) != 2010315a1350SMichael S. Tsirkin (desc->class & ~desc->fw_ign_bits)) { 2011315a1350SMichael S. Tsirkin desc++; 2012315a1350SMichael S. Tsirkin } 2013315a1350SMichael S. Tsirkin 2014315a1350SMichael S. Tsirkin if (desc->desc) { 2015315a1350SMichael S. Tsirkin name = desc->fw_name; 2016315a1350SMichael S. Tsirkin } 2017315a1350SMichael S. Tsirkin 2018315a1350SMichael S. Tsirkin if (name) { 2019315a1350SMichael S. Tsirkin pstrcpy(buf, len, name); 2020315a1350SMichael S. Tsirkin } else { 2021315a1350SMichael S. Tsirkin snprintf(buf, len, "pci%04x,%04x", 2022315a1350SMichael S. Tsirkin pci_get_word(d->config + PCI_VENDOR_ID), 2023315a1350SMichael S. Tsirkin pci_get_word(d->config + PCI_DEVICE_ID)); 2024315a1350SMichael S. Tsirkin } 2025315a1350SMichael S. Tsirkin 2026315a1350SMichael S. Tsirkin return buf; 2027315a1350SMichael S. Tsirkin } 2028315a1350SMichael S. Tsirkin 2029315a1350SMichael S. Tsirkin static char *pcibus_get_fw_dev_path(DeviceState *dev) 2030315a1350SMichael S. Tsirkin { 2031315a1350SMichael S. Tsirkin PCIDevice *d = (PCIDevice *)dev; 2032315a1350SMichael S. Tsirkin char path[50], name[33]; 2033315a1350SMichael S. Tsirkin int off; 2034315a1350SMichael S. Tsirkin 2035315a1350SMichael S. Tsirkin off = snprintf(path, sizeof(path), "%s@%x", 2036315a1350SMichael S. Tsirkin pci_dev_fw_name(dev, name, sizeof name), 2037315a1350SMichael S. Tsirkin PCI_SLOT(d->devfn)); 2038315a1350SMichael S. Tsirkin if (PCI_FUNC(d->devfn)) 2039315a1350SMichael S. Tsirkin snprintf(path + off, sizeof(path) + off, ",%x", PCI_FUNC(d->devfn)); 2040315a1350SMichael S. Tsirkin return g_strdup(path); 2041315a1350SMichael S. Tsirkin } 2042315a1350SMichael S. Tsirkin 2043315a1350SMichael S. Tsirkin static char *pcibus_get_dev_path(DeviceState *dev) 2044315a1350SMichael S. Tsirkin { 2045315a1350SMichael S. Tsirkin PCIDevice *d = container_of(dev, PCIDevice, qdev); 2046315a1350SMichael S. Tsirkin PCIDevice *t; 2047315a1350SMichael S. Tsirkin int slot_depth; 2048315a1350SMichael S. Tsirkin /* Path format: Domain:00:Slot.Function:Slot.Function....:Slot.Function. 2049315a1350SMichael S. Tsirkin * 00 is added here to make this format compatible with 2050315a1350SMichael S. Tsirkin * domain:Bus:Slot.Func for systems without nested PCI bridges. 2051315a1350SMichael S. Tsirkin * Slot.Function list specifies the slot and function numbers for all 2052315a1350SMichael S. Tsirkin * devices on the path from root to the specific device. */ 2053315a1350SMichael S. Tsirkin char domain[] = "DDDD:00"; 2054315a1350SMichael S. Tsirkin char slot[] = ":SS.F"; 2055315a1350SMichael S. Tsirkin int domain_len = sizeof domain - 1 /* For '\0' */; 2056315a1350SMichael S. Tsirkin int slot_len = sizeof slot - 1 /* For '\0' */; 2057315a1350SMichael S. Tsirkin int path_len; 2058315a1350SMichael S. Tsirkin char *path, *p; 2059315a1350SMichael S. Tsirkin int s; 2060315a1350SMichael S. Tsirkin 2061315a1350SMichael S. Tsirkin /* Calculate # of slots on path between device and root. */; 2062315a1350SMichael S. Tsirkin slot_depth = 0; 2063315a1350SMichael S. Tsirkin for (t = d; t; t = t->bus->parent_dev) { 2064315a1350SMichael S. Tsirkin ++slot_depth; 2065315a1350SMichael S. Tsirkin } 2066315a1350SMichael S. Tsirkin 2067315a1350SMichael S. Tsirkin path_len = domain_len + slot_len * slot_depth; 2068315a1350SMichael S. Tsirkin 2069315a1350SMichael S. Tsirkin /* Allocate memory, fill in the terminating null byte. */ 2070315a1350SMichael S. Tsirkin path = g_malloc(path_len + 1 /* For '\0' */); 2071315a1350SMichael S. Tsirkin path[path_len] = '\0'; 2072315a1350SMichael S. Tsirkin 2073315a1350SMichael S. Tsirkin /* First field is the domain. */ 2074315a1350SMichael S. Tsirkin s = snprintf(domain, sizeof domain, "%04x:00", pci_find_domain(d->bus)); 2075315a1350SMichael S. Tsirkin assert(s == domain_len); 2076315a1350SMichael S. Tsirkin memcpy(path, domain, domain_len); 2077315a1350SMichael S. Tsirkin 2078315a1350SMichael S. Tsirkin /* Fill in slot numbers. We walk up from device to root, so need to print 2079315a1350SMichael S. Tsirkin * them in the reverse order, last to first. */ 2080315a1350SMichael S. Tsirkin p = path + path_len; 2081315a1350SMichael S. Tsirkin for (t = d; t; t = t->bus->parent_dev) { 2082315a1350SMichael S. Tsirkin p -= slot_len; 2083315a1350SMichael S. Tsirkin s = snprintf(slot, sizeof slot, ":%02x.%x", 2084315a1350SMichael S. Tsirkin PCI_SLOT(t->devfn), PCI_FUNC(t->devfn)); 2085315a1350SMichael S. Tsirkin assert(s == slot_len); 2086315a1350SMichael S. Tsirkin memcpy(p, slot, slot_len); 2087315a1350SMichael S. Tsirkin } 2088315a1350SMichael S. Tsirkin 2089315a1350SMichael S. Tsirkin return path; 2090315a1350SMichael S. Tsirkin } 2091315a1350SMichael S. Tsirkin 2092315a1350SMichael S. Tsirkin static int pci_qdev_find_recursive(PCIBus *bus, 2093315a1350SMichael S. Tsirkin const char *id, PCIDevice **pdev) 2094315a1350SMichael S. Tsirkin { 2095315a1350SMichael S. Tsirkin DeviceState *qdev = qdev_find_recursive(&bus->qbus, id); 2096315a1350SMichael S. Tsirkin if (!qdev) { 2097315a1350SMichael S. Tsirkin return -ENODEV; 2098315a1350SMichael S. Tsirkin } 2099315a1350SMichael S. Tsirkin 2100315a1350SMichael S. Tsirkin /* roughly check if given qdev is pci device */ 2101315a1350SMichael S. Tsirkin if (object_dynamic_cast(OBJECT(qdev), TYPE_PCI_DEVICE)) { 2102315a1350SMichael S. Tsirkin *pdev = PCI_DEVICE(qdev); 2103315a1350SMichael S. Tsirkin return 0; 2104315a1350SMichael S. Tsirkin } 2105315a1350SMichael S. Tsirkin return -EINVAL; 2106315a1350SMichael S. Tsirkin } 2107315a1350SMichael S. Tsirkin 2108315a1350SMichael S. Tsirkin int pci_qdev_find_device(const char *id, PCIDevice **pdev) 2109315a1350SMichael S. Tsirkin { 2110315a1350SMichael S. Tsirkin struct PCIHostBus *host; 2111315a1350SMichael S. Tsirkin int rc = -ENODEV; 2112315a1350SMichael S. Tsirkin 2113315a1350SMichael S. Tsirkin QLIST_FOREACH(host, &host_buses, next) { 2114315a1350SMichael S. Tsirkin int tmp = pci_qdev_find_recursive(host->bus, id, pdev); 2115315a1350SMichael S. Tsirkin if (!tmp) { 2116315a1350SMichael S. Tsirkin rc = 0; 2117315a1350SMichael S. Tsirkin break; 2118315a1350SMichael S. Tsirkin } 2119315a1350SMichael S. Tsirkin if (tmp != -ENODEV) { 2120315a1350SMichael S. Tsirkin rc = tmp; 2121315a1350SMichael S. Tsirkin } 2122315a1350SMichael S. Tsirkin } 2123315a1350SMichael S. Tsirkin 2124315a1350SMichael S. Tsirkin return rc; 2125315a1350SMichael S. Tsirkin } 2126315a1350SMichael S. Tsirkin 2127315a1350SMichael S. Tsirkin MemoryRegion *pci_address_space(PCIDevice *dev) 2128315a1350SMichael S. Tsirkin { 2129315a1350SMichael S. Tsirkin return dev->bus->address_space_mem; 2130315a1350SMichael S. Tsirkin } 2131315a1350SMichael S. Tsirkin 2132315a1350SMichael S. Tsirkin MemoryRegion *pci_address_space_io(PCIDevice *dev) 2133315a1350SMichael S. Tsirkin { 2134315a1350SMichael S. Tsirkin return dev->bus->address_space_io; 2135315a1350SMichael S. Tsirkin } 2136315a1350SMichael S. Tsirkin 2137315a1350SMichael S. Tsirkin static void pci_device_class_init(ObjectClass *klass, void *data) 2138315a1350SMichael S. Tsirkin { 2139315a1350SMichael S. Tsirkin DeviceClass *k = DEVICE_CLASS(klass); 2140315a1350SMichael S. Tsirkin k->init = pci_qdev_init; 2141315a1350SMichael S. Tsirkin k->unplug = pci_unplug_device; 2142315a1350SMichael S. Tsirkin k->exit = pci_unregister_device; 2143315a1350SMichael S. Tsirkin k->bus_type = TYPE_PCI_BUS; 2144315a1350SMichael S. Tsirkin k->props = pci_props; 2145315a1350SMichael S. Tsirkin } 2146315a1350SMichael S. Tsirkin 2147315a1350SMichael S. Tsirkin void pci_setup_iommu(PCIBus *bus, PCIDMAContextFunc fn, void *opaque) 2148315a1350SMichael S. Tsirkin { 2149315a1350SMichael S. Tsirkin bus->dma_context_fn = fn; 2150315a1350SMichael S. Tsirkin bus->dma_context_opaque = opaque; 2151315a1350SMichael S. Tsirkin } 2152315a1350SMichael S. Tsirkin 2153315a1350SMichael S. Tsirkin static TypeInfo pci_device_type_info = { 2154315a1350SMichael S. Tsirkin .name = TYPE_PCI_DEVICE, 2155315a1350SMichael S. Tsirkin .parent = TYPE_DEVICE, 2156315a1350SMichael S. Tsirkin .instance_size = sizeof(PCIDevice), 2157315a1350SMichael S. Tsirkin .abstract = true, 2158315a1350SMichael S. Tsirkin .class_size = sizeof(PCIDeviceClass), 2159315a1350SMichael S. Tsirkin .class_init = pci_device_class_init, 2160315a1350SMichael S. Tsirkin }; 2161315a1350SMichael S. Tsirkin 2162315a1350SMichael S. Tsirkin static void pci_register_types(void) 2163315a1350SMichael S. Tsirkin { 2164315a1350SMichael S. Tsirkin type_register_static(&pci_bus_info); 2165315a1350SMichael S. Tsirkin type_register_static(&pci_device_type_info); 2166315a1350SMichael S. Tsirkin } 2167315a1350SMichael S. Tsirkin 2168315a1350SMichael S. Tsirkin type_init(pci_register_types) 2169