122773d60SMichael S. Tsirkin /* 222773d60SMichael S. Tsirkin * QEMU PCI test device 322773d60SMichael S. Tsirkin * 422773d60SMichael S. Tsirkin * Copyright (c) 2012 Red Hat Inc. 522773d60SMichael S. Tsirkin * Author: Michael S. Tsirkin <mst@redhat.com> 622773d60SMichael S. Tsirkin * 722773d60SMichael S. Tsirkin * This program is free software; you can redistribute it and/or modify 822773d60SMichael S. Tsirkin * it under the terms of the GNU General Public License as published by 922773d60SMichael S. Tsirkin * the Free Software Foundation; either version 2 of the License, or 1022773d60SMichael S. Tsirkin * (at your option) any later version. 1122773d60SMichael S. Tsirkin * 1222773d60SMichael S. Tsirkin * This program is distributed in the hope that it will be useful, 1322773d60SMichael S. Tsirkin * but WITHOUT ANY WARRANTY; without even the implied warranty of 1422773d60SMichael S. Tsirkin * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1522773d60SMichael S. Tsirkin * GNU General Public License for more details. 1622773d60SMichael S. Tsirkin * 1722773d60SMichael S. Tsirkin * You should have received a copy of the GNU General Public License along 1822773d60SMichael S. Tsirkin * with this program; if not, see <http://www.gnu.org/licenses/>. 1922773d60SMichael S. Tsirkin */ 200b8fa32fSMarkus Armbruster 2197d5408fSPeter Maydell #include "qemu/osdep.h" 22edf5ca5dSMarkus Armbruster #include "hw/pci/pci_device.h" 23a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h" 2422773d60SMichael S. Tsirkin #include "qemu/event_notifier.h" 250b8fa32fSMarkus Armbruster #include "qemu/module.h" 26*32cad1ffSPhilippe Mathieu-Daudé #include "system/kvm.h" 27db1015e9SEduardo Habkost #include "qom/object.h" 2822773d60SMichael S. Tsirkin 2922773d60SMichael S. Tsirkin typedef struct PCITestDevHdr { 3022773d60SMichael S. Tsirkin uint8_t test; 3122773d60SMichael S. Tsirkin uint8_t width; 3222773d60SMichael S. Tsirkin uint8_t pad0[2]; 3322773d60SMichael S. Tsirkin uint32_t offset; 3422773d60SMichael S. Tsirkin uint8_t data; 3522773d60SMichael S. Tsirkin uint8_t pad1[3]; 3622773d60SMichael S. Tsirkin uint32_t count; 3722773d60SMichael S. Tsirkin uint8_t name[]; 3822773d60SMichael S. Tsirkin } PCITestDevHdr; 3922773d60SMichael S. Tsirkin 4022773d60SMichael S. Tsirkin typedef struct IOTest { 4122773d60SMichael S. Tsirkin MemoryRegion *mr; 4222773d60SMichael S. Tsirkin EventNotifier notifier; 4322773d60SMichael S. Tsirkin bool hasnotifier; 4422773d60SMichael S. Tsirkin unsigned size; 4522773d60SMichael S. Tsirkin bool match_data; 4622773d60SMichael S. Tsirkin PCITestDevHdr *hdr; 4722773d60SMichael S. Tsirkin unsigned bufsize; 4822773d60SMichael S. Tsirkin } IOTest; 4922773d60SMichael S. Tsirkin 5022773d60SMichael S. Tsirkin #define IOTEST_DATAMATCH 0xFA 5122773d60SMichael S. Tsirkin #define IOTEST_NOMATCH 0xCE 5222773d60SMichael S. Tsirkin 5322773d60SMichael S. Tsirkin #define IOTEST_IOSIZE 128 5422773d60SMichael S. Tsirkin #define IOTEST_MEMSIZE 2048 5522773d60SMichael S. Tsirkin 5622773d60SMichael S. Tsirkin static const char *iotest_test[] = { 5722773d60SMichael S. Tsirkin "no-eventfd", 5822773d60SMichael S. Tsirkin "wildcard-eventfd", 5922773d60SMichael S. Tsirkin "datamatch-eventfd" 6022773d60SMichael S. Tsirkin }; 6122773d60SMichael S. Tsirkin 6222773d60SMichael S. Tsirkin static const char *iotest_type[] = { 6322773d60SMichael S. Tsirkin "mmio", 6422773d60SMichael S. Tsirkin "portio" 6522773d60SMichael S. Tsirkin }; 6622773d60SMichael S. Tsirkin 6722773d60SMichael S. Tsirkin #define IOTEST_TEST(i) (iotest_test[((i) % ARRAY_SIZE(iotest_test))]) 6822773d60SMichael S. Tsirkin #define IOTEST_TYPE(i) (iotest_type[((i) / ARRAY_SIZE(iotest_test))]) 6922773d60SMichael S. Tsirkin #define IOTEST_MAX_TEST (ARRAY_SIZE(iotest_test)) 7022773d60SMichael S. Tsirkin #define IOTEST_MAX_TYPE (ARRAY_SIZE(iotest_type)) 7122773d60SMichael S. Tsirkin #define IOTEST_MAX (IOTEST_MAX_TEST * IOTEST_MAX_TYPE) 7222773d60SMichael S. Tsirkin 7322773d60SMichael S. Tsirkin enum { 7422773d60SMichael S. Tsirkin IOTEST_ACCESS_NAME, 7522773d60SMichael S. Tsirkin IOTEST_ACCESS_DATA, 7622773d60SMichael S. Tsirkin IOTEST_ACCESS_MAX, 7722773d60SMichael S. Tsirkin }; 7822773d60SMichael S. Tsirkin 7922773d60SMichael S. Tsirkin #define IOTEST_ACCESS_TYPE uint8_t 8022773d60SMichael S. Tsirkin #define IOTEST_ACCESS_WIDTH (sizeof(uint8_t)) 8122773d60SMichael S. Tsirkin 82db1015e9SEduardo Habkost struct PCITestDevState { 836d27a409SAndreas Färber /*< private >*/ 846d27a409SAndreas Färber PCIDevice parent_obj; 856d27a409SAndreas Färber /*< public >*/ 866d27a409SAndreas Färber 8722773d60SMichael S. Tsirkin MemoryRegion mmio; 8822773d60SMichael S. Tsirkin MemoryRegion portio; 8922773d60SMichael S. Tsirkin IOTest *tests; 9022773d60SMichael S. Tsirkin int current; 9141746334SGerd Hoffmann 9241746334SGerd Hoffmann uint64_t membar_size; 9341746334SGerd Hoffmann MemoryRegion membar; 94db1015e9SEduardo Habkost }; 9522773d60SMichael S. Tsirkin 9640108d0aSPeter Crosthwaite #define TYPE_PCI_TEST_DEV "pci-testdev" 9740108d0aSPeter Crosthwaite 988063396bSEduardo Habkost OBJECT_DECLARE_SIMPLE_TYPE(PCITestDevState, PCI_TEST_DEV) 9940108d0aSPeter Crosthwaite 10022773d60SMichael S. Tsirkin #define IOTEST_IS_MEM(i) (strcmp(IOTEST_TYPE(i), "portio")) 10122773d60SMichael S. Tsirkin #define IOTEST_REGION(d, i) (IOTEST_IS_MEM(i) ? &(d)->mmio : &(d)->portio) 10222773d60SMichael S. Tsirkin #define IOTEST_SIZE(i) (IOTEST_IS_MEM(i) ? IOTEST_MEMSIZE : IOTEST_IOSIZE) 10322773d60SMichael S. Tsirkin #define IOTEST_PCI_BAR(i) (IOTEST_IS_MEM(i) ? PCI_BASE_ADDRESS_SPACE_MEMORY : \ 10422773d60SMichael S. Tsirkin PCI_BASE_ADDRESS_SPACE_IO) 10522773d60SMichael S. Tsirkin 10622773d60SMichael S. Tsirkin static int pci_testdev_start(IOTest *test) 10722773d60SMichael S. Tsirkin { 10822773d60SMichael S. Tsirkin test->hdr->count = 0; 10922773d60SMichael S. Tsirkin if (!test->hasnotifier) { 11022773d60SMichael S. Tsirkin return 0; 11122773d60SMichael S. Tsirkin } 11222773d60SMichael S. Tsirkin event_notifier_test_and_clear(&test->notifier); 11322773d60SMichael S. Tsirkin memory_region_add_eventfd(test->mr, 11422773d60SMichael S. Tsirkin le32_to_cpu(test->hdr->offset), 11522773d60SMichael S. Tsirkin test->size, 11622773d60SMichael S. Tsirkin test->match_data, 11722773d60SMichael S. Tsirkin test->hdr->data, 11822773d60SMichael S. Tsirkin &test->notifier); 11922773d60SMichael S. Tsirkin return 0; 12022773d60SMichael S. Tsirkin } 12122773d60SMichael S. Tsirkin 12222773d60SMichael S. Tsirkin static void pci_testdev_stop(IOTest *test) 12322773d60SMichael S. Tsirkin { 12422773d60SMichael S. Tsirkin if (!test->hasnotifier) { 12522773d60SMichael S. Tsirkin return; 12622773d60SMichael S. Tsirkin } 12722773d60SMichael S. Tsirkin memory_region_del_eventfd(test->mr, 12822773d60SMichael S. Tsirkin le32_to_cpu(test->hdr->offset), 12922773d60SMichael S. Tsirkin test->size, 13022773d60SMichael S. Tsirkin test->match_data, 13122773d60SMichael S. Tsirkin test->hdr->data, 13222773d60SMichael S. Tsirkin &test->notifier); 13322773d60SMichael S. Tsirkin } 13422773d60SMichael S. Tsirkin 13522773d60SMichael S. Tsirkin static void 13622773d60SMichael S. Tsirkin pci_testdev_reset(PCITestDevState *d) 13722773d60SMichael S. Tsirkin { 13822773d60SMichael S. Tsirkin if (d->current == -1) { 13922773d60SMichael S. Tsirkin return; 14022773d60SMichael S. Tsirkin } 14122773d60SMichael S. Tsirkin pci_testdev_stop(&d->tests[d->current]); 14222773d60SMichael S. Tsirkin d->current = -1; 14322773d60SMichael S. Tsirkin } 14422773d60SMichael S. Tsirkin 14522773d60SMichael S. Tsirkin static void pci_testdev_inc(IOTest *test, unsigned inc) 14622773d60SMichael S. Tsirkin { 14722773d60SMichael S. Tsirkin uint32_t c = le32_to_cpu(test->hdr->count); 14822773d60SMichael S. Tsirkin test->hdr->count = cpu_to_le32(c + inc); 14922773d60SMichael S. Tsirkin } 15022773d60SMichael S. Tsirkin 15122773d60SMichael S. Tsirkin static void 15222773d60SMichael S. Tsirkin pci_testdev_write(void *opaque, hwaddr addr, uint64_t val, 15322773d60SMichael S. Tsirkin unsigned size, int type) 15422773d60SMichael S. Tsirkin { 15522773d60SMichael S. Tsirkin PCITestDevState *d = opaque; 15622773d60SMichael S. Tsirkin IOTest *test; 15722773d60SMichael S. Tsirkin int t, r; 15822773d60SMichael S. Tsirkin 15922773d60SMichael S. Tsirkin if (addr == offsetof(PCITestDevHdr, test)) { 16022773d60SMichael S. Tsirkin pci_testdev_reset(d); 16122773d60SMichael S. Tsirkin if (val >= IOTEST_MAX_TEST) { 16222773d60SMichael S. Tsirkin return; 16322773d60SMichael S. Tsirkin } 16422773d60SMichael S. Tsirkin t = type * IOTEST_MAX_TEST + val; 16522773d60SMichael S. Tsirkin r = pci_testdev_start(&d->tests[t]); 16622773d60SMichael S. Tsirkin if (r < 0) { 16722773d60SMichael S. Tsirkin return; 16822773d60SMichael S. Tsirkin } 16922773d60SMichael S. Tsirkin d->current = t; 17022773d60SMichael S. Tsirkin return; 17122773d60SMichael S. Tsirkin } 17222773d60SMichael S. Tsirkin if (d->current < 0) { 17322773d60SMichael S. Tsirkin return; 17422773d60SMichael S. Tsirkin } 17522773d60SMichael S. Tsirkin test = &d->tests[d->current]; 17622773d60SMichael S. Tsirkin if (addr != le32_to_cpu(test->hdr->offset)) { 17722773d60SMichael S. Tsirkin return; 17822773d60SMichael S. Tsirkin } 17922773d60SMichael S. Tsirkin if (test->match_data && test->size != size) { 18022773d60SMichael S. Tsirkin return; 18122773d60SMichael S. Tsirkin } 18222773d60SMichael S. Tsirkin if (test->match_data && val != test->hdr->data) { 18322773d60SMichael S. Tsirkin return; 18422773d60SMichael S. Tsirkin } 18522773d60SMichael S. Tsirkin pci_testdev_inc(test, 1); 18622773d60SMichael S. Tsirkin } 18722773d60SMichael S. Tsirkin 18822773d60SMichael S. Tsirkin static uint64_t 18922773d60SMichael S. Tsirkin pci_testdev_read(void *opaque, hwaddr addr, unsigned size) 19022773d60SMichael S. Tsirkin { 19122773d60SMichael S. Tsirkin PCITestDevState *d = opaque; 19222773d60SMichael S. Tsirkin const char *buf; 19322773d60SMichael S. Tsirkin IOTest *test; 19422773d60SMichael S. Tsirkin if (d->current < 0) { 19522773d60SMichael S. Tsirkin return 0; 19622773d60SMichael S. Tsirkin } 19722773d60SMichael S. Tsirkin test = &d->tests[d->current]; 19822773d60SMichael S. Tsirkin buf = (const char *)test->hdr; 19922773d60SMichael S. Tsirkin if (addr + size >= test->bufsize) { 20022773d60SMichael S. Tsirkin return 0; 20122773d60SMichael S. Tsirkin } 20222773d60SMichael S. Tsirkin if (test->hasnotifier) { 20322773d60SMichael S. Tsirkin event_notifier_test_and_clear(&test->notifier); 20422773d60SMichael S. Tsirkin } 20522773d60SMichael S. Tsirkin return buf[addr]; 20622773d60SMichael S. Tsirkin } 20722773d60SMichael S. Tsirkin 20822773d60SMichael S. Tsirkin static void 20922773d60SMichael S. Tsirkin pci_testdev_mmio_write(void *opaque, hwaddr addr, uint64_t val, 21022773d60SMichael S. Tsirkin unsigned size) 21122773d60SMichael S. Tsirkin { 21222773d60SMichael S. Tsirkin pci_testdev_write(opaque, addr, val, size, 0); 21322773d60SMichael S. Tsirkin } 21422773d60SMichael S. Tsirkin 21522773d60SMichael S. Tsirkin static void 21622773d60SMichael S. Tsirkin pci_testdev_pio_write(void *opaque, hwaddr addr, uint64_t val, 21722773d60SMichael S. Tsirkin unsigned size) 21822773d60SMichael S. Tsirkin { 21922773d60SMichael S. Tsirkin pci_testdev_write(opaque, addr, val, size, 1); 22022773d60SMichael S. Tsirkin } 22122773d60SMichael S. Tsirkin 22222773d60SMichael S. Tsirkin static const MemoryRegionOps pci_testdev_mmio_ops = { 22322773d60SMichael S. Tsirkin .read = pci_testdev_read, 22422773d60SMichael S. Tsirkin .write = pci_testdev_mmio_write, 22522773d60SMichael S. Tsirkin .endianness = DEVICE_LITTLE_ENDIAN, 22622773d60SMichael S. Tsirkin .impl = { 22722773d60SMichael S. Tsirkin .min_access_size = 1, 22822773d60SMichael S. Tsirkin .max_access_size = 1, 22922773d60SMichael S. Tsirkin }, 23022773d60SMichael S. Tsirkin }; 23122773d60SMichael S. Tsirkin 23222773d60SMichael S. Tsirkin static const MemoryRegionOps pci_testdev_pio_ops = { 23322773d60SMichael S. Tsirkin .read = pci_testdev_read, 23422773d60SMichael S. Tsirkin .write = pci_testdev_pio_write, 23522773d60SMichael S. Tsirkin .endianness = DEVICE_LITTLE_ENDIAN, 23622773d60SMichael S. Tsirkin .impl = { 23722773d60SMichael S. Tsirkin .min_access_size = 1, 23822773d60SMichael S. Tsirkin .max_access_size = 1, 23922773d60SMichael S. Tsirkin }, 24022773d60SMichael S. Tsirkin }; 24122773d60SMichael S. Tsirkin 2429af21dbeSMarkus Armbruster static void pci_testdev_realize(PCIDevice *pci_dev, Error **errp) 24322773d60SMichael S. Tsirkin { 24440108d0aSPeter Crosthwaite PCITestDevState *d = PCI_TEST_DEV(pci_dev); 24522773d60SMichael S. Tsirkin uint8_t *pci_conf; 24622773d60SMichael S. Tsirkin char *name; 24722773d60SMichael S. Tsirkin int r, i; 24822773d60SMichael S. Tsirkin 2496d27a409SAndreas Färber pci_conf = pci_dev->config; 25022773d60SMichael S. Tsirkin 25122773d60SMichael S. Tsirkin pci_conf[PCI_INTERRUPT_PIN] = 0; /* no interrupt pin */ 25222773d60SMichael S. Tsirkin 2533c161542SPaolo Bonzini memory_region_init_io(&d->mmio, OBJECT(d), &pci_testdev_mmio_ops, d, 25422773d60SMichael S. Tsirkin "pci-testdev-mmio", IOTEST_MEMSIZE * 2); 2553c161542SPaolo Bonzini memory_region_init_io(&d->portio, OBJECT(d), &pci_testdev_pio_ops, d, 25622773d60SMichael S. Tsirkin "pci-testdev-portio", IOTEST_IOSIZE * 2); 2576d27a409SAndreas Färber pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio); 2586d27a409SAndreas Färber pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &d->portio); 25922773d60SMichael S. Tsirkin 26041746334SGerd Hoffmann if (d->membar_size) { 26141746334SGerd Hoffmann memory_region_init(&d->membar, OBJECT(d), "pci-testdev-membar", 26241746334SGerd Hoffmann d->membar_size); 26341746334SGerd Hoffmann pci_register_bar(pci_dev, 2, 26441746334SGerd Hoffmann PCI_BASE_ADDRESS_SPACE_MEMORY | 26541746334SGerd Hoffmann PCI_BASE_ADDRESS_MEM_PREFETCH | 26641746334SGerd Hoffmann PCI_BASE_ADDRESS_MEM_TYPE_64, 26741746334SGerd Hoffmann &d->membar); 26841746334SGerd Hoffmann } 26941746334SGerd Hoffmann 27022773d60SMichael S. Tsirkin d->current = -1; 27122773d60SMichael S. Tsirkin d->tests = g_malloc0(IOTEST_MAX * sizeof *d->tests); 27222773d60SMichael S. Tsirkin for (i = 0; i < IOTEST_MAX; ++i) { 27322773d60SMichael S. Tsirkin IOTest *test = &d->tests[i]; 27422773d60SMichael S. Tsirkin name = g_strdup_printf("%s-%s", IOTEST_TYPE(i), IOTEST_TEST(i)); 27522773d60SMichael S. Tsirkin test->bufsize = sizeof(PCITestDevHdr) + strlen(name) + 1; 27622773d60SMichael S. Tsirkin test->hdr = g_malloc0(test->bufsize); 27722773d60SMichael S. Tsirkin memcpy(test->hdr->name, name, strlen(name) + 1); 27822773d60SMichael S. Tsirkin g_free(name); 27922773d60SMichael S. Tsirkin test->hdr->offset = cpu_to_le32(IOTEST_SIZE(i) + i * IOTEST_ACCESS_WIDTH); 28022773d60SMichael S. Tsirkin test->match_data = strcmp(IOTEST_TEST(i), "wildcard-eventfd"); 281126e7f78SPaolo Bonzini if (IOTEST_IS_MEM(i) && !test->match_data) { 28245aa4e8eSMichael S. Tsirkin test->size = 0; 28345aa4e8eSMichael S. Tsirkin } else { 28445aa4e8eSMichael S. Tsirkin test->size = IOTEST_ACCESS_WIDTH; 28545aa4e8eSMichael S. Tsirkin } 28622773d60SMichael S. Tsirkin test->hdr->test = i; 28722773d60SMichael S. Tsirkin test->hdr->data = test->match_data ? IOTEST_DATAMATCH : IOTEST_NOMATCH; 28822773d60SMichael S. Tsirkin test->hdr->width = IOTEST_ACCESS_WIDTH; 28922773d60SMichael S. Tsirkin test->mr = IOTEST_REGION(d, i); 29022773d60SMichael S. Tsirkin if (!strcmp(IOTEST_TEST(i), "no-eventfd")) { 29122773d60SMichael S. Tsirkin test->hasnotifier = false; 29222773d60SMichael S. Tsirkin continue; 29322773d60SMichael S. Tsirkin } 29422773d60SMichael S. Tsirkin r = event_notifier_init(&test->notifier, 0); 29522773d60SMichael S. Tsirkin assert(r >= 0); 29622773d60SMichael S. Tsirkin test->hasnotifier = true; 29722773d60SMichael S. Tsirkin } 29822773d60SMichael S. Tsirkin } 29922773d60SMichael S. Tsirkin 30022773d60SMichael S. Tsirkin static void 30122773d60SMichael S. Tsirkin pci_testdev_uninit(PCIDevice *dev) 30222773d60SMichael S. Tsirkin { 30340108d0aSPeter Crosthwaite PCITestDevState *d = PCI_TEST_DEV(dev); 30422773d60SMichael S. Tsirkin int i; 30522773d60SMichael S. Tsirkin 30622773d60SMichael S. Tsirkin pci_testdev_reset(d); 30722773d60SMichael S. Tsirkin for (i = 0; i < IOTEST_MAX; ++i) { 30822773d60SMichael S. Tsirkin if (d->tests[i].hasnotifier) { 30922773d60SMichael S. Tsirkin event_notifier_cleanup(&d->tests[i].notifier); 31022773d60SMichael S. Tsirkin } 31122773d60SMichael S. Tsirkin g_free(d->tests[i].hdr); 31222773d60SMichael S. Tsirkin } 31322773d60SMichael S. Tsirkin g_free(d->tests); 31422773d60SMichael S. Tsirkin } 31522773d60SMichael S. Tsirkin 31622773d60SMichael S. Tsirkin static void qdev_pci_testdev_reset(DeviceState *dev) 31722773d60SMichael S. Tsirkin { 31840108d0aSPeter Crosthwaite PCITestDevState *d = PCI_TEST_DEV(dev); 31922773d60SMichael S. Tsirkin pci_testdev_reset(d); 32022773d60SMichael S. Tsirkin } 32122773d60SMichael S. Tsirkin 32230029973SRichard Henderson static const Property pci_testdev_properties[] = { 32341746334SGerd Hoffmann DEFINE_PROP_SIZE("membar", PCITestDevState, membar_size, 0), 32441746334SGerd Hoffmann DEFINE_PROP_END_OF_LIST(), 32541746334SGerd Hoffmann }; 32641746334SGerd Hoffmann 32722773d60SMichael S. Tsirkin static void pci_testdev_class_init(ObjectClass *klass, void *data) 32822773d60SMichael S. Tsirkin { 32922773d60SMichael S. Tsirkin DeviceClass *dc = DEVICE_CLASS(klass); 33022773d60SMichael S. Tsirkin PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 33122773d60SMichael S. Tsirkin 3329af21dbeSMarkus Armbruster k->realize = pci_testdev_realize; 33322773d60SMichael S. Tsirkin k->exit = pci_testdev_uninit; 33422773d60SMichael S. Tsirkin k->vendor_id = PCI_VENDOR_ID_REDHAT; 33522773d60SMichael S. Tsirkin k->device_id = PCI_DEVICE_ID_REDHAT_TEST; 33622773d60SMichael S. Tsirkin k->revision = 0x00; 33722773d60SMichael S. Tsirkin k->class_id = PCI_CLASS_OTHERS; 33822773d60SMichael S. Tsirkin dc->desc = "PCI Test Device"; 339125ee0edSMarcel Apfelbaum set_bit(DEVICE_CATEGORY_MISC, dc->categories); 340e3d08143SPeter Maydell device_class_set_legacy_reset(dc, qdev_pci_testdev_reset); 3414f67d30bSMarc-André Lureau device_class_set_props(dc, pci_testdev_properties); 34222773d60SMichael S. Tsirkin } 34322773d60SMichael S. Tsirkin 34422773d60SMichael S. Tsirkin static const TypeInfo pci_testdev_info = { 34540108d0aSPeter Crosthwaite .name = TYPE_PCI_TEST_DEV, 34622773d60SMichael S. Tsirkin .parent = TYPE_PCI_DEVICE, 34722773d60SMichael S. Tsirkin .instance_size = sizeof(PCITestDevState), 34822773d60SMichael S. Tsirkin .class_init = pci_testdev_class_init, 349fd3b02c8SEduardo Habkost .interfaces = (InterfaceInfo[]) { 350fd3b02c8SEduardo Habkost { INTERFACE_CONVENTIONAL_PCI_DEVICE }, 351fd3b02c8SEduardo Habkost { }, 352fd3b02c8SEduardo Habkost }, 35322773d60SMichael S. Tsirkin }; 35422773d60SMichael S. Tsirkin 35522773d60SMichael S. Tsirkin static void pci_testdev_register_types(void) 35622773d60SMichael S. Tsirkin { 35722773d60SMichael S. Tsirkin type_register_static(&pci_testdev_info); 35822773d60SMichael S. Tsirkin } 35922773d60SMichael S. Tsirkin 36022773d60SMichael S. Tsirkin type_init(pci_testdev_register_types) 361