xref: /openbmc/qemu/tests/qtest/libqos/pci.c (revision 3df72d1c)
1 /*
2  * libqos PCI bindings
3  *
4  * Copyright IBM, Corp. 2012-2013
5  *
6  * Authors:
7  *  Anthony Liguori   <aliguori@us.ibm.com>
8  *
9  * This work is licensed under the terms of the GNU GPL, version 2 or later.
10  * See the COPYING file in the top-level directory.
11  */
12 
13 #include "qemu/osdep.h"
14 #include "pci.h"
15 
16 #include "hw/pci/pci.h"
17 #include "hw/pci/pci_bridge.h"
18 #include "hw/pci/pci_regs.h"
19 #include "qemu/host-utils.h"
20 #include "qgraph.h"
21 
qpci_device_foreach(QPCIBus * bus,int vendor_id,int device_id,void (* func)(QPCIDevice * dev,int devfn,void * data),void * data)22 void qpci_device_foreach(QPCIBus *bus, int vendor_id, int device_id,
23                          void (*func)(QPCIDevice *dev, int devfn, void *data),
24                          void *data)
25 {
26     int slot;
27 
28     for (slot = 0; slot < 32; slot++) {
29         int fn;
30 
31         for (fn = 0; fn < 8; fn++) {
32             QPCIDevice *dev;
33 
34             dev = qpci_device_find(bus, QPCI_DEVFN(slot, fn));
35             if (!dev) {
36                 continue;
37             }
38 
39             if (vendor_id != -1 &&
40                 qpci_config_readw(dev, PCI_VENDOR_ID) != vendor_id) {
41                 g_free(dev);
42                 continue;
43             }
44 
45             if (device_id != -1 &&
46                 qpci_config_readw(dev, PCI_DEVICE_ID) != device_id) {
47                 g_free(dev);
48                 continue;
49             }
50 
51             func(dev, QPCI_DEVFN(slot, fn), data);
52         }
53     }
54 }
55 
qpci_has_buggy_msi(QPCIDevice * dev)56 bool qpci_has_buggy_msi(QPCIDevice *dev)
57 {
58     return dev->bus->has_buggy_msi;
59 }
60 
qpci_check_buggy_msi(QPCIDevice * dev)61 bool qpci_check_buggy_msi(QPCIDevice *dev)
62 {
63     if (qpci_has_buggy_msi(dev)) {
64         g_test_skip("Skipping due to incomplete support for MSI");
65         return true;
66     }
67     return false;
68 }
69 
qpci_device_set(QPCIDevice * dev,QPCIBus * bus,int devfn)70 static void qpci_device_set(QPCIDevice *dev, QPCIBus *bus, int devfn)
71 {
72     g_assert(dev);
73 
74     dev->bus = bus;
75     dev->devfn = devfn;
76 }
77 
qpci_device_find(QPCIBus * bus,int devfn)78 QPCIDevice *qpci_device_find(QPCIBus *bus, int devfn)
79 {
80     QPCIDevice *dev;
81 
82     dev = g_malloc0(sizeof(*dev));
83     qpci_device_set(dev, bus, devfn);
84 
85     if (qpci_config_readw(dev, PCI_VENDOR_ID) == 0xFFFF) {
86         g_free(dev);
87         return NULL;
88     }
89 
90     return dev;
91 }
92 
qpci_device_init(QPCIDevice * dev,QPCIBus * bus,QPCIAddress * addr)93 void qpci_device_init(QPCIDevice *dev, QPCIBus *bus, QPCIAddress *addr)
94 {
95     uint16_t vendor_id, device_id;
96 
97     qpci_device_set(dev, bus, addr->devfn);
98     vendor_id = qpci_config_readw(dev, PCI_VENDOR_ID);
99     device_id = qpci_config_readw(dev, PCI_DEVICE_ID);
100     g_assert(!addr->vendor_id || vendor_id == addr->vendor_id);
101     g_assert(!addr->device_id || device_id == addr->device_id);
102 }
103 
qpci_find_resource_reserve_capability(QPCIDevice * dev)104 static uint8_t qpci_find_resource_reserve_capability(QPCIDevice *dev)
105 {
106     uint16_t device_id;
107     uint8_t cap = 0;
108 
109     if (qpci_config_readw(dev, PCI_VENDOR_ID) != PCI_VENDOR_ID_REDHAT) {
110         return 0;
111     }
112 
113     device_id = qpci_config_readw(dev, PCI_DEVICE_ID);
114 
115     if (device_id != PCI_DEVICE_ID_REDHAT_PCIE_RP &&
116         device_id != PCI_DEVICE_ID_REDHAT_BRIDGE) {
117         return 0;
118     }
119 
120     do {
121         cap = qpci_find_capability(dev, PCI_CAP_ID_VNDR, cap);
122     } while (cap &&
123              qpci_config_readb(dev, cap + REDHAT_PCI_CAP_TYPE_OFFSET) !=
124              REDHAT_PCI_CAP_RESOURCE_RESERVE);
125     if (cap) {
126         uint8_t cap_len = qpci_config_readb(dev, cap + PCI_CAP_FLAGS);
127         if (cap_len < REDHAT_PCI_CAP_RES_RESERVE_CAP_SIZE) {
128             return 0;
129         }
130     }
131     return cap;
132 }
133 
qpci_secondary_buses_rec(QPCIBus * qbus,int bus,int * pci_bus)134 static void qpci_secondary_buses_rec(QPCIBus *qbus, int bus, int *pci_bus)
135 {
136     QPCIDevice *dev;
137     uint16_t class;
138     uint8_t pribus, secbus, subbus;
139     int index;
140 
141     for (index = 0; index < 32; index++) {
142         dev = qpci_device_find(qbus, QPCI_DEVFN(bus + index, 0));
143         if (dev == NULL) {
144             continue;
145         }
146         class = qpci_config_readw(dev, PCI_CLASS_DEVICE);
147         if (class == PCI_CLASS_BRIDGE_PCI) {
148             qpci_config_writeb(dev, PCI_SECONDARY_BUS, 255);
149             qpci_config_writeb(dev, PCI_SUBORDINATE_BUS, 0);
150         }
151         g_free(dev);
152     }
153 
154     for (index = 0; index < 32; index++) {
155         dev = qpci_device_find(qbus, QPCI_DEVFN(bus + index, 0));
156         if (dev == NULL) {
157             continue;
158         }
159         class = qpci_config_readw(dev, PCI_CLASS_DEVICE);
160         if (class != PCI_CLASS_BRIDGE_PCI) {
161             g_free(dev);
162             continue;
163         }
164 
165         pribus = qpci_config_readb(dev, PCI_PRIMARY_BUS);
166         if (pribus != bus) {
167             qpci_config_writeb(dev, PCI_PRIMARY_BUS, bus);
168         }
169 
170         secbus = qpci_config_readb(dev, PCI_SECONDARY_BUS);
171         (*pci_bus)++;
172         if (*pci_bus != secbus) {
173             secbus = *pci_bus;
174             qpci_config_writeb(dev, PCI_SECONDARY_BUS, secbus);
175         }
176 
177         subbus = qpci_config_readb(dev, PCI_SUBORDINATE_BUS);
178         qpci_config_writeb(dev, PCI_SUBORDINATE_BUS, 255);
179 
180         qpci_secondary_buses_rec(qbus, secbus << 5, pci_bus);
181 
182         if (subbus != *pci_bus) {
183             uint8_t res_bus = *pci_bus;
184             uint8_t cap = qpci_find_resource_reserve_capability(dev);
185 
186             if (cap) {
187                 uint32_t tmp_res_bus;
188 
189                 tmp_res_bus = qpci_config_readl(dev, cap +
190                                             REDHAT_PCI_CAP_RES_RESERVE_BUS_RES);
191                 if (tmp_res_bus != (uint32_t)-1) {
192                     res_bus = tmp_res_bus & 0xFF;
193                     if ((uint8_t)(res_bus + secbus) < secbus ||
194                         (uint8_t)(res_bus + secbus) < res_bus) {
195                         res_bus = 0;
196                     }
197                     if (secbus + res_bus > *pci_bus) {
198                         res_bus = secbus + res_bus;
199                     }
200                 }
201             }
202             subbus = res_bus;
203             *pci_bus = res_bus;
204         }
205 
206         qpci_config_writeb(dev, PCI_SUBORDINATE_BUS, subbus);
207         g_free(dev);
208     }
209 }
210 
qpci_secondary_buses_init(QPCIBus * bus)211 int qpci_secondary_buses_init(QPCIBus *bus)
212 {
213     int last_bus = 0;
214 
215     qpci_secondary_buses_rec(bus, 0, &last_bus);
216 
217     return last_bus;
218 }
219 
220 
qpci_device_enable(QPCIDevice * dev)221 void qpci_device_enable(QPCIDevice *dev)
222 {
223     uint16_t cmd;
224 
225     /* FIXME -- does this need to be a bus callout? */
226     cmd = qpci_config_readw(dev, PCI_COMMAND);
227     cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
228     qpci_config_writew(dev, PCI_COMMAND, cmd);
229 
230     /* Verify the bits are now set. */
231     cmd = qpci_config_readw(dev, PCI_COMMAND);
232     g_assert_cmphex(cmd & PCI_COMMAND_IO, ==, PCI_COMMAND_IO);
233     g_assert_cmphex(cmd & PCI_COMMAND_MEMORY, ==, PCI_COMMAND_MEMORY);
234     g_assert_cmphex(cmd & PCI_COMMAND_MASTER, ==, PCI_COMMAND_MASTER);
235 }
236 
237 /**
238  * qpci_find_capability:
239  * @dev: the PCI device
240  * @id: the PCI Capability ID (PCI_CAP_ID_*)
241  * @start_addr: 0 to begin iteration or the last return value to continue
242  *              iteration
243  *
244  * Iterate over the PCI Capabilities List.
245  *
246  * Returns: PCI Configuration Space offset of the capabililty structure or
247  *          0 if no further matching capability is found
248  */
qpci_find_capability(QPCIDevice * dev,uint8_t id,uint8_t start_addr)249 uint8_t qpci_find_capability(QPCIDevice *dev, uint8_t id, uint8_t start_addr)
250 {
251     uint8_t cap;
252     uint8_t addr;
253 
254     if (start_addr) {
255         addr = qpci_config_readb(dev, start_addr + PCI_CAP_LIST_NEXT);
256     } else {
257         addr = qpci_config_readb(dev, PCI_CAPABILITY_LIST);
258     }
259 
260     do {
261         cap = qpci_config_readb(dev, addr);
262         if (cap != id) {
263             addr = qpci_config_readb(dev, addr + PCI_CAP_LIST_NEXT);
264         }
265     } while (cap != id && addr != 0);
266 
267     return addr;
268 }
269 
qpci_msix_enable(QPCIDevice * dev)270 void qpci_msix_enable(QPCIDevice *dev)
271 {
272     uint8_t addr;
273     uint16_t val;
274     uint32_t table;
275     uint8_t bir_table;
276     uint8_t bir_pba;
277 
278     addr = qpci_find_capability(dev, PCI_CAP_ID_MSIX, 0);
279     g_assert_cmphex(addr, !=, 0);
280 
281     val = qpci_config_readw(dev, addr + PCI_MSIX_FLAGS);
282     qpci_config_writew(dev, addr + PCI_MSIX_FLAGS, val | PCI_MSIX_FLAGS_ENABLE);
283 
284     table = qpci_config_readl(dev, addr + PCI_MSIX_TABLE);
285     bir_table = table & PCI_MSIX_FLAGS_BIRMASK;
286     dev->msix_table_bar = qpci_iomap(dev, bir_table, NULL);
287     dev->msix_table_off = table & ~PCI_MSIX_FLAGS_BIRMASK;
288 
289     table = qpci_config_readl(dev, addr + PCI_MSIX_PBA);
290     bir_pba = table & PCI_MSIX_FLAGS_BIRMASK;
291     if (bir_pba != bir_table) {
292         dev->msix_pba_bar = qpci_iomap(dev, bir_pba, NULL);
293     } else {
294         dev->msix_pba_bar = dev->msix_table_bar;
295     }
296     dev->msix_pba_off = table & ~PCI_MSIX_FLAGS_BIRMASK;
297 
298     dev->msix_enabled = true;
299 }
300 
qpci_msix_disable(QPCIDevice * dev)301 void qpci_msix_disable(QPCIDevice *dev)
302 {
303     uint8_t addr;
304     uint16_t val;
305 
306     g_assert(dev->msix_enabled);
307     addr = qpci_find_capability(dev, PCI_CAP_ID_MSIX, 0);
308     g_assert_cmphex(addr, !=, 0);
309     val = qpci_config_readw(dev, addr + PCI_MSIX_FLAGS);
310     qpci_config_writew(dev, addr + PCI_MSIX_FLAGS,
311                                                 val & ~PCI_MSIX_FLAGS_ENABLE);
312 
313     if (dev->msix_pba_bar.addr != dev->msix_table_bar.addr) {
314         qpci_iounmap(dev, dev->msix_pba_bar);
315     }
316     qpci_iounmap(dev, dev->msix_table_bar);
317 
318     dev->msix_enabled = 0;
319     dev->msix_table_off = 0;
320     dev->msix_pba_off = 0;
321 }
322 
qpci_msix_pending(QPCIDevice * dev,uint16_t entry)323 bool qpci_msix_pending(QPCIDevice *dev, uint16_t entry)
324 {
325     uint32_t pba_entry;
326     uint8_t bit_n = entry % 32;
327     uint64_t  off = (entry / 32) * PCI_MSIX_ENTRY_SIZE / 4;
328 
329     g_assert(dev->msix_enabled);
330     pba_entry = qpci_io_readl(dev, dev->msix_pba_bar, dev->msix_pba_off + off);
331     qpci_io_writel(dev, dev->msix_pba_bar, dev->msix_pba_off + off,
332                    pba_entry & ~(1 << bit_n));
333     return (pba_entry & (1 << bit_n)) != 0;
334 }
335 
qpci_msix_masked(QPCIDevice * dev,uint16_t entry)336 bool qpci_msix_masked(QPCIDevice *dev, uint16_t entry)
337 {
338     uint8_t addr;
339     uint16_t val;
340     uint64_t vector_off = dev->msix_table_off + entry * PCI_MSIX_ENTRY_SIZE;
341 
342     g_assert(dev->msix_enabled);
343     addr = qpci_find_capability(dev, PCI_CAP_ID_MSIX, 0);
344     g_assert_cmphex(addr, !=, 0);
345     val = qpci_config_readw(dev, addr + PCI_MSIX_FLAGS);
346 
347     if (val & PCI_MSIX_FLAGS_MASKALL) {
348         return true;
349     } else {
350         return (qpci_io_readl(dev, dev->msix_table_bar,
351                               vector_off + PCI_MSIX_ENTRY_VECTOR_CTRL)
352                 & PCI_MSIX_ENTRY_CTRL_MASKBIT) != 0;
353     }
354 }
355 
qpci_msix_table_size(QPCIDevice * dev)356 uint16_t qpci_msix_table_size(QPCIDevice *dev)
357 {
358     uint8_t addr;
359     uint16_t control;
360 
361     addr = qpci_find_capability(dev, PCI_CAP_ID_MSIX, 0);
362     g_assert_cmphex(addr, !=, 0);
363 
364     control = qpci_config_readw(dev, addr + PCI_MSIX_FLAGS);
365     return (control & PCI_MSIX_FLAGS_QSIZE) + 1;
366 }
367 
qpci_config_readb(QPCIDevice * dev,uint8_t offset)368 uint8_t qpci_config_readb(QPCIDevice *dev, uint8_t offset)
369 {
370     return dev->bus->config_readb(dev->bus, dev->devfn, offset);
371 }
372 
qpci_config_readw(QPCIDevice * dev,uint8_t offset)373 uint16_t qpci_config_readw(QPCIDevice *dev, uint8_t offset)
374 {
375     return dev->bus->config_readw(dev->bus, dev->devfn, offset);
376 }
377 
qpci_config_readl(QPCIDevice * dev,uint8_t offset)378 uint32_t qpci_config_readl(QPCIDevice *dev, uint8_t offset)
379 {
380     return dev->bus->config_readl(dev->bus, dev->devfn, offset);
381 }
382 
383 
qpci_config_writeb(QPCIDevice * dev,uint8_t offset,uint8_t value)384 void qpci_config_writeb(QPCIDevice *dev, uint8_t offset, uint8_t value)
385 {
386     dev->bus->config_writeb(dev->bus, dev->devfn, offset, value);
387 }
388 
qpci_config_writew(QPCIDevice * dev,uint8_t offset,uint16_t value)389 void qpci_config_writew(QPCIDevice *dev, uint8_t offset, uint16_t value)
390 {
391     dev->bus->config_writew(dev->bus, dev->devfn, offset, value);
392 }
393 
qpci_config_writel(QPCIDevice * dev,uint8_t offset,uint32_t value)394 void qpci_config_writel(QPCIDevice *dev, uint8_t offset, uint32_t value)
395 {
396     dev->bus->config_writel(dev->bus, dev->devfn, offset, value);
397 }
398 
qpci_io_readb(QPCIDevice * dev,QPCIBar token,uint64_t off)399 uint8_t qpci_io_readb(QPCIDevice *dev, QPCIBar token, uint64_t off)
400 {
401     QPCIBus *bus = dev->bus;
402 
403     if (token.is_io) {
404         return bus->pio_readb(bus, token.addr + off);
405     } else {
406         uint8_t val;
407 
408         bus->memread(dev->bus, token.addr + off, &val, sizeof(val));
409         return val;
410     }
411 }
412 
qpci_io_readw(QPCIDevice * dev,QPCIBar token,uint64_t off)413 uint16_t qpci_io_readw(QPCIDevice *dev, QPCIBar token, uint64_t off)
414 {
415     QPCIBus *bus = dev->bus;
416 
417     if (token.is_io) {
418         return bus->pio_readw(bus, token.addr + off);
419     } else {
420         uint16_t val;
421 
422         bus->memread(bus, token.addr + off, &val, sizeof(val));
423         return le16_to_cpu(val);
424     }
425 }
426 
qpci_io_readl(QPCIDevice * dev,QPCIBar token,uint64_t off)427 uint32_t qpci_io_readl(QPCIDevice *dev, QPCIBar token, uint64_t off)
428 {
429     QPCIBus *bus = dev->bus;
430 
431     if (token.is_io) {
432         return bus->pio_readl(bus, token.addr + off);
433     } else {
434         uint32_t val;
435 
436         bus->memread(dev->bus, token.addr + off, &val, sizeof(val));
437         return le32_to_cpu(val);
438     }
439 }
440 
qpci_io_readq(QPCIDevice * dev,QPCIBar token,uint64_t off)441 uint64_t qpci_io_readq(QPCIDevice *dev, QPCIBar token, uint64_t off)
442 {
443     QPCIBus *bus = dev->bus;
444 
445     if (token.is_io) {
446         return bus->pio_readq(bus, token.addr + off);
447     } else {
448         uint64_t val;
449 
450         bus->memread(bus, token.addr + off, &val, sizeof(val));
451         return le64_to_cpu(val);
452     }
453 }
454 
qpci_io_writeb(QPCIDevice * dev,QPCIBar token,uint64_t off,uint8_t value)455 void qpci_io_writeb(QPCIDevice *dev, QPCIBar token, uint64_t off,
456                     uint8_t value)
457 {
458     QPCIBus *bus = dev->bus;
459 
460     if (token.is_io) {
461         bus->pio_writeb(bus, token.addr + off, value);
462     } else {
463         bus->memwrite(bus, token.addr + off, &value, sizeof(value));
464     }
465 }
466 
qpci_io_writew(QPCIDevice * dev,QPCIBar token,uint64_t off,uint16_t value)467 void qpci_io_writew(QPCIDevice *dev, QPCIBar token, uint64_t off,
468                     uint16_t value)
469 {
470     QPCIBus *bus = dev->bus;
471 
472     if (token.is_io) {
473         bus->pio_writew(bus, token.addr + off, value);
474     } else {
475         value = cpu_to_le16(value);
476         bus->memwrite(bus, token.addr + off, &value, sizeof(value));
477     }
478 }
479 
qpci_io_writel(QPCIDevice * dev,QPCIBar token,uint64_t off,uint32_t value)480 void qpci_io_writel(QPCIDevice *dev, QPCIBar token, uint64_t off,
481                     uint32_t value)
482 {
483     QPCIBus *bus = dev->bus;
484 
485     if (token.is_io) {
486         bus->pio_writel(bus, token.addr + off, value);
487     } else {
488         value = cpu_to_le32(value);
489         bus->memwrite(bus, token.addr + off, &value, sizeof(value));
490     }
491 }
492 
qpci_io_writeq(QPCIDevice * dev,QPCIBar token,uint64_t off,uint64_t value)493 void qpci_io_writeq(QPCIDevice *dev, QPCIBar token, uint64_t off,
494                     uint64_t value)
495 {
496     QPCIBus *bus = dev->bus;
497 
498     if (token.is_io) {
499         bus->pio_writeq(bus, token.addr + off, value);
500     } else {
501         value = cpu_to_le64(value);
502         bus->memwrite(bus, token.addr + off, &value, sizeof(value));
503     }
504 }
505 
qpci_memread(QPCIDevice * dev,QPCIBar token,uint64_t off,void * buf,size_t len)506 void qpci_memread(QPCIDevice *dev, QPCIBar token, uint64_t off,
507                   void *buf, size_t len)
508 {
509     g_assert(!token.is_io);
510     dev->bus->memread(dev->bus, token.addr + off, buf, len);
511 }
512 
qpci_memwrite(QPCIDevice * dev,QPCIBar token,uint64_t off,const void * buf,size_t len)513 void qpci_memwrite(QPCIDevice *dev, QPCIBar token, uint64_t off,
514                    const void *buf, size_t len)
515 {
516     g_assert(!token.is_io);
517     dev->bus->memwrite(dev->bus, token.addr + off, buf, len);
518 }
519 
qpci_iomap(QPCIDevice * dev,int barno,uint64_t * sizeptr)520 QPCIBar qpci_iomap(QPCIDevice *dev, int barno, uint64_t *sizeptr)
521 {
522     QPCIBus *bus = dev->bus;
523     static const int bar_reg_map[] = {
524         PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_1, PCI_BASE_ADDRESS_2,
525         PCI_BASE_ADDRESS_3, PCI_BASE_ADDRESS_4, PCI_BASE_ADDRESS_5,
526     };
527     QPCIBar bar;
528     int bar_reg;
529     uint32_t addr, size;
530     uint32_t io_type;
531     uint64_t loc;
532 
533     g_assert(barno >= 0 && barno <= 5);
534     bar_reg = bar_reg_map[barno];
535 
536     qpci_config_writel(dev, bar_reg, 0xFFFFFFFF);
537     addr = qpci_config_readl(dev, bar_reg);
538 
539     io_type = addr & PCI_BASE_ADDRESS_SPACE;
540     if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
541         addr &= PCI_BASE_ADDRESS_IO_MASK;
542     } else {
543         addr &= PCI_BASE_ADDRESS_MEM_MASK;
544     }
545 
546     g_assert(addr); /* Must have *some* size bits */
547 
548     size = 1U << ctz32(addr);
549     if (sizeptr) {
550         *sizeptr = size;
551     }
552 
553     if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
554         loc = QEMU_ALIGN_UP(bus->pio_alloc_ptr, size);
555 
556         g_assert(loc >= bus->pio_alloc_ptr);
557         g_assert(loc + size <= bus->pio_limit);
558 
559         bus->pio_alloc_ptr = loc + size;
560         bar.is_io = true;
561 
562         qpci_config_writel(dev, bar_reg, loc | PCI_BASE_ADDRESS_SPACE_IO);
563     } else {
564         loc = QEMU_ALIGN_UP(bus->mmio_alloc_ptr, size);
565 
566         /* Check for space */
567         g_assert(loc >= bus->mmio_alloc_ptr);
568         g_assert(loc + size <= bus->mmio_limit);
569 
570         bus->mmio_alloc_ptr = loc + size;
571         bar.is_io = false;
572 
573         qpci_config_writel(dev, bar_reg, loc);
574     }
575 
576     bar.addr = loc;
577     return bar;
578 }
579 
qpci_iounmap(QPCIDevice * dev,QPCIBar bar)580 void qpci_iounmap(QPCIDevice *dev, QPCIBar bar)
581 {
582     /* FIXME */
583 }
584 
qpci_legacy_iomap(QPCIDevice * dev,uint16_t addr)585 QPCIBar qpci_legacy_iomap(QPCIDevice *dev, uint16_t addr)
586 {
587     QPCIBar bar = { .addr = addr, .is_io = true };
588     return bar;
589 }
590 
add_qpci_address(QOSGraphEdgeOptions * opts,QPCIAddress * addr)591 void add_qpci_address(QOSGraphEdgeOptions *opts, QPCIAddress *addr)
592 {
593     g_assert(addr);
594     g_assert(opts);
595 
596     opts->arg = addr;
597     opts->size_arg = sizeof(QPCIAddress);
598 }
599