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