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" 2222773d60SMichael S. Tsirkin #include "hw/pci/pci.h" 23a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h" 2422773d60SMichael S. Tsirkin #include "qemu/event_notifier.h" 250b8fa32fSMarkus Armbruster #include "qemu/module.h" 2677ac58ddSPaolo Bonzini #include "sysemu/kvm.h" 27*db1015e9SEduardo 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 82*db1015e9SEduardo 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; 94*db1015e9SEduardo Habkost }; 95*db1015e9SEduardo Habkost typedef struct PCITestDevState PCITestDevState; 9622773d60SMichael S. Tsirkin 9740108d0aSPeter Crosthwaite #define TYPE_PCI_TEST_DEV "pci-testdev" 9840108d0aSPeter Crosthwaite 9940108d0aSPeter Crosthwaite #define PCI_TEST_DEV(obj) \ 10040108d0aSPeter Crosthwaite OBJECT_CHECK(PCITestDevState, (obj), TYPE_PCI_TEST_DEV) 10140108d0aSPeter Crosthwaite 10222773d60SMichael S. Tsirkin #define IOTEST_IS_MEM(i) (strcmp(IOTEST_TYPE(i), "portio")) 10322773d60SMichael S. Tsirkin #define IOTEST_REGION(d, i) (IOTEST_IS_MEM(i) ? &(d)->mmio : &(d)->portio) 10422773d60SMichael S. Tsirkin #define IOTEST_SIZE(i) (IOTEST_IS_MEM(i) ? IOTEST_MEMSIZE : IOTEST_IOSIZE) 10522773d60SMichael S. Tsirkin #define IOTEST_PCI_BAR(i) (IOTEST_IS_MEM(i) ? PCI_BASE_ADDRESS_SPACE_MEMORY : \ 10622773d60SMichael S. Tsirkin PCI_BASE_ADDRESS_SPACE_IO) 10722773d60SMichael S. Tsirkin 10822773d60SMichael S. Tsirkin static int pci_testdev_start(IOTest *test) 10922773d60SMichael S. Tsirkin { 11022773d60SMichael S. Tsirkin test->hdr->count = 0; 11122773d60SMichael S. Tsirkin if (!test->hasnotifier) { 11222773d60SMichael S. Tsirkin return 0; 11322773d60SMichael S. Tsirkin } 11422773d60SMichael S. Tsirkin event_notifier_test_and_clear(&test->notifier); 11522773d60SMichael S. Tsirkin memory_region_add_eventfd(test->mr, 11622773d60SMichael S. Tsirkin le32_to_cpu(test->hdr->offset), 11722773d60SMichael S. Tsirkin test->size, 11822773d60SMichael S. Tsirkin test->match_data, 11922773d60SMichael S. Tsirkin test->hdr->data, 12022773d60SMichael S. Tsirkin &test->notifier); 12122773d60SMichael S. Tsirkin return 0; 12222773d60SMichael S. Tsirkin } 12322773d60SMichael S. Tsirkin 12422773d60SMichael S. Tsirkin static void pci_testdev_stop(IOTest *test) 12522773d60SMichael S. Tsirkin { 12622773d60SMichael S. Tsirkin if (!test->hasnotifier) { 12722773d60SMichael S. Tsirkin return; 12822773d60SMichael S. Tsirkin } 12922773d60SMichael S. Tsirkin memory_region_del_eventfd(test->mr, 13022773d60SMichael S. Tsirkin le32_to_cpu(test->hdr->offset), 13122773d60SMichael S. Tsirkin test->size, 13222773d60SMichael S. Tsirkin test->match_data, 13322773d60SMichael S. Tsirkin test->hdr->data, 13422773d60SMichael S. Tsirkin &test->notifier); 13522773d60SMichael S. Tsirkin } 13622773d60SMichael S. Tsirkin 13722773d60SMichael S. Tsirkin static void 13822773d60SMichael S. Tsirkin pci_testdev_reset(PCITestDevState *d) 13922773d60SMichael S. Tsirkin { 14022773d60SMichael S. Tsirkin if (d->current == -1) { 14122773d60SMichael S. Tsirkin return; 14222773d60SMichael S. Tsirkin } 14322773d60SMichael S. Tsirkin pci_testdev_stop(&d->tests[d->current]); 14422773d60SMichael S. Tsirkin d->current = -1; 14522773d60SMichael S. Tsirkin } 14622773d60SMichael S. Tsirkin 14722773d60SMichael S. Tsirkin static void pci_testdev_inc(IOTest *test, unsigned inc) 14822773d60SMichael S. Tsirkin { 14922773d60SMichael S. Tsirkin uint32_t c = le32_to_cpu(test->hdr->count); 15022773d60SMichael S. Tsirkin test->hdr->count = cpu_to_le32(c + inc); 15122773d60SMichael S. Tsirkin } 15222773d60SMichael S. Tsirkin 15322773d60SMichael S. Tsirkin static void 15422773d60SMichael S. Tsirkin pci_testdev_write(void *opaque, hwaddr addr, uint64_t val, 15522773d60SMichael S. Tsirkin unsigned size, int type) 15622773d60SMichael S. Tsirkin { 15722773d60SMichael S. Tsirkin PCITestDevState *d = opaque; 15822773d60SMichael S. Tsirkin IOTest *test; 15922773d60SMichael S. Tsirkin int t, r; 16022773d60SMichael S. Tsirkin 16122773d60SMichael S. Tsirkin if (addr == offsetof(PCITestDevHdr, test)) { 16222773d60SMichael S. Tsirkin pci_testdev_reset(d); 16322773d60SMichael S. Tsirkin if (val >= IOTEST_MAX_TEST) { 16422773d60SMichael S. Tsirkin return; 16522773d60SMichael S. Tsirkin } 16622773d60SMichael S. Tsirkin t = type * IOTEST_MAX_TEST + val; 16722773d60SMichael S. Tsirkin r = pci_testdev_start(&d->tests[t]); 16822773d60SMichael S. Tsirkin if (r < 0) { 16922773d60SMichael S. Tsirkin return; 17022773d60SMichael S. Tsirkin } 17122773d60SMichael S. Tsirkin d->current = t; 17222773d60SMichael S. Tsirkin return; 17322773d60SMichael S. Tsirkin } 17422773d60SMichael S. Tsirkin if (d->current < 0) { 17522773d60SMichael S. Tsirkin return; 17622773d60SMichael S. Tsirkin } 17722773d60SMichael S. Tsirkin test = &d->tests[d->current]; 17822773d60SMichael S. Tsirkin if (addr != le32_to_cpu(test->hdr->offset)) { 17922773d60SMichael S. Tsirkin return; 18022773d60SMichael S. Tsirkin } 18122773d60SMichael S. Tsirkin if (test->match_data && test->size != size) { 18222773d60SMichael S. Tsirkin return; 18322773d60SMichael S. Tsirkin } 18422773d60SMichael S. Tsirkin if (test->match_data && val != test->hdr->data) { 18522773d60SMichael S. Tsirkin return; 18622773d60SMichael S. Tsirkin } 18722773d60SMichael S. Tsirkin pci_testdev_inc(test, 1); 18822773d60SMichael S. Tsirkin } 18922773d60SMichael S. Tsirkin 19022773d60SMichael S. Tsirkin static uint64_t 19122773d60SMichael S. Tsirkin pci_testdev_read(void *opaque, hwaddr addr, unsigned size) 19222773d60SMichael S. Tsirkin { 19322773d60SMichael S. Tsirkin PCITestDevState *d = opaque; 19422773d60SMichael S. Tsirkin const char *buf; 19522773d60SMichael S. Tsirkin IOTest *test; 19622773d60SMichael S. Tsirkin if (d->current < 0) { 19722773d60SMichael S. Tsirkin return 0; 19822773d60SMichael S. Tsirkin } 19922773d60SMichael S. Tsirkin test = &d->tests[d->current]; 20022773d60SMichael S. Tsirkin buf = (const char *)test->hdr; 20122773d60SMichael S. Tsirkin if (addr + size >= test->bufsize) { 20222773d60SMichael S. Tsirkin return 0; 20322773d60SMichael S. Tsirkin } 20422773d60SMichael S. Tsirkin if (test->hasnotifier) { 20522773d60SMichael S. Tsirkin event_notifier_test_and_clear(&test->notifier); 20622773d60SMichael S. Tsirkin } 20722773d60SMichael S. Tsirkin return buf[addr]; 20822773d60SMichael S. Tsirkin } 20922773d60SMichael S. Tsirkin 21022773d60SMichael S. Tsirkin static void 21122773d60SMichael S. Tsirkin pci_testdev_mmio_write(void *opaque, hwaddr addr, uint64_t val, 21222773d60SMichael S. Tsirkin unsigned size) 21322773d60SMichael S. Tsirkin { 21422773d60SMichael S. Tsirkin pci_testdev_write(opaque, addr, val, size, 0); 21522773d60SMichael S. Tsirkin } 21622773d60SMichael S. Tsirkin 21722773d60SMichael S. Tsirkin static void 21822773d60SMichael S. Tsirkin pci_testdev_pio_write(void *opaque, hwaddr addr, uint64_t val, 21922773d60SMichael S. Tsirkin unsigned size) 22022773d60SMichael S. Tsirkin { 22122773d60SMichael S. Tsirkin pci_testdev_write(opaque, addr, val, size, 1); 22222773d60SMichael S. Tsirkin } 22322773d60SMichael S. Tsirkin 22422773d60SMichael S. Tsirkin static const MemoryRegionOps pci_testdev_mmio_ops = { 22522773d60SMichael S. Tsirkin .read = pci_testdev_read, 22622773d60SMichael S. Tsirkin .write = pci_testdev_mmio_write, 22722773d60SMichael S. Tsirkin .endianness = DEVICE_LITTLE_ENDIAN, 22822773d60SMichael S. Tsirkin .impl = { 22922773d60SMichael S. Tsirkin .min_access_size = 1, 23022773d60SMichael S. Tsirkin .max_access_size = 1, 23122773d60SMichael S. Tsirkin }, 23222773d60SMichael S. Tsirkin }; 23322773d60SMichael S. Tsirkin 23422773d60SMichael S. Tsirkin static const MemoryRegionOps pci_testdev_pio_ops = { 23522773d60SMichael S. Tsirkin .read = pci_testdev_read, 23622773d60SMichael S. Tsirkin .write = pci_testdev_pio_write, 23722773d60SMichael S. Tsirkin .endianness = DEVICE_LITTLE_ENDIAN, 23822773d60SMichael S. Tsirkin .impl = { 23922773d60SMichael S. Tsirkin .min_access_size = 1, 24022773d60SMichael S. Tsirkin .max_access_size = 1, 24122773d60SMichael S. Tsirkin }, 24222773d60SMichael S. Tsirkin }; 24322773d60SMichael S. Tsirkin 2449af21dbeSMarkus Armbruster static void pci_testdev_realize(PCIDevice *pci_dev, Error **errp) 24522773d60SMichael S. Tsirkin { 24640108d0aSPeter Crosthwaite PCITestDevState *d = PCI_TEST_DEV(pci_dev); 24722773d60SMichael S. Tsirkin uint8_t *pci_conf; 24822773d60SMichael S. Tsirkin char *name; 24922773d60SMichael S. Tsirkin int r, i; 25045aa4e8eSMichael S. Tsirkin bool fastmmio = kvm_ioeventfd_any_length_enabled(); 25122773d60SMichael S. Tsirkin 2526d27a409SAndreas Färber pci_conf = pci_dev->config; 25322773d60SMichael S. Tsirkin 25422773d60SMichael S. Tsirkin pci_conf[PCI_INTERRUPT_PIN] = 0; /* no interrupt pin */ 25522773d60SMichael S. Tsirkin 2563c161542SPaolo Bonzini memory_region_init_io(&d->mmio, OBJECT(d), &pci_testdev_mmio_ops, d, 25722773d60SMichael S. Tsirkin "pci-testdev-mmio", IOTEST_MEMSIZE * 2); 2583c161542SPaolo Bonzini memory_region_init_io(&d->portio, OBJECT(d), &pci_testdev_pio_ops, d, 25922773d60SMichael S. Tsirkin "pci-testdev-portio", IOTEST_IOSIZE * 2); 2606d27a409SAndreas Färber pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio); 2616d27a409SAndreas Färber pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &d->portio); 26222773d60SMichael S. Tsirkin 26341746334SGerd Hoffmann if (d->membar_size) { 26441746334SGerd Hoffmann memory_region_init(&d->membar, OBJECT(d), "pci-testdev-membar", 26541746334SGerd Hoffmann d->membar_size); 26641746334SGerd Hoffmann pci_register_bar(pci_dev, 2, 26741746334SGerd Hoffmann PCI_BASE_ADDRESS_SPACE_MEMORY | 26841746334SGerd Hoffmann PCI_BASE_ADDRESS_MEM_PREFETCH | 26941746334SGerd Hoffmann PCI_BASE_ADDRESS_MEM_TYPE_64, 27041746334SGerd Hoffmann &d->membar); 27141746334SGerd Hoffmann } 27241746334SGerd Hoffmann 27322773d60SMichael S. Tsirkin d->current = -1; 27422773d60SMichael S. Tsirkin d->tests = g_malloc0(IOTEST_MAX * sizeof *d->tests); 27522773d60SMichael S. Tsirkin for (i = 0; i < IOTEST_MAX; ++i) { 27622773d60SMichael S. Tsirkin IOTest *test = &d->tests[i]; 27722773d60SMichael S. Tsirkin name = g_strdup_printf("%s-%s", IOTEST_TYPE(i), IOTEST_TEST(i)); 27822773d60SMichael S. Tsirkin test->bufsize = sizeof(PCITestDevHdr) + strlen(name) + 1; 27922773d60SMichael S. Tsirkin test->hdr = g_malloc0(test->bufsize); 28022773d60SMichael S. Tsirkin memcpy(test->hdr->name, name, strlen(name) + 1); 28122773d60SMichael S. Tsirkin g_free(name); 28222773d60SMichael S. Tsirkin test->hdr->offset = cpu_to_le32(IOTEST_SIZE(i) + i * IOTEST_ACCESS_WIDTH); 28322773d60SMichael S. Tsirkin test->match_data = strcmp(IOTEST_TEST(i), "wildcard-eventfd"); 28445aa4e8eSMichael S. Tsirkin if (fastmmio && IOTEST_IS_MEM(i) && !test->match_data) { 28545aa4e8eSMichael S. Tsirkin test->size = 0; 28645aa4e8eSMichael S. Tsirkin } else { 28745aa4e8eSMichael S. Tsirkin test->size = IOTEST_ACCESS_WIDTH; 28845aa4e8eSMichael S. Tsirkin } 28922773d60SMichael S. Tsirkin test->hdr->test = i; 29022773d60SMichael S. Tsirkin test->hdr->data = test->match_data ? IOTEST_DATAMATCH : IOTEST_NOMATCH; 29122773d60SMichael S. Tsirkin test->hdr->width = IOTEST_ACCESS_WIDTH; 29222773d60SMichael S. Tsirkin test->mr = IOTEST_REGION(d, i); 29322773d60SMichael S. Tsirkin if (!strcmp(IOTEST_TEST(i), "no-eventfd")) { 29422773d60SMichael S. Tsirkin test->hasnotifier = false; 29522773d60SMichael S. Tsirkin continue; 29622773d60SMichael S. Tsirkin } 29722773d60SMichael S. Tsirkin r = event_notifier_init(&test->notifier, 0); 29822773d60SMichael S. Tsirkin assert(r >= 0); 29922773d60SMichael S. Tsirkin test->hasnotifier = true; 30022773d60SMichael S. Tsirkin } 30122773d60SMichael S. Tsirkin } 30222773d60SMichael S. Tsirkin 30322773d60SMichael S. Tsirkin static void 30422773d60SMichael S. Tsirkin pci_testdev_uninit(PCIDevice *dev) 30522773d60SMichael S. Tsirkin { 30640108d0aSPeter Crosthwaite PCITestDevState *d = PCI_TEST_DEV(dev); 30722773d60SMichael S. Tsirkin int i; 30822773d60SMichael S. Tsirkin 30922773d60SMichael S. Tsirkin pci_testdev_reset(d); 31022773d60SMichael S. Tsirkin for (i = 0; i < IOTEST_MAX; ++i) { 31122773d60SMichael S. Tsirkin if (d->tests[i].hasnotifier) { 31222773d60SMichael S. Tsirkin event_notifier_cleanup(&d->tests[i].notifier); 31322773d60SMichael S. Tsirkin } 31422773d60SMichael S. Tsirkin g_free(d->tests[i].hdr); 31522773d60SMichael S. Tsirkin } 31622773d60SMichael S. Tsirkin g_free(d->tests); 31722773d60SMichael S. Tsirkin } 31822773d60SMichael S. Tsirkin 31922773d60SMichael S. Tsirkin static void qdev_pci_testdev_reset(DeviceState *dev) 32022773d60SMichael S. Tsirkin { 32140108d0aSPeter Crosthwaite PCITestDevState *d = PCI_TEST_DEV(dev); 32222773d60SMichael S. Tsirkin pci_testdev_reset(d); 32322773d60SMichael S. Tsirkin } 32422773d60SMichael S. Tsirkin 32541746334SGerd Hoffmann static Property pci_testdev_properties[] = { 32641746334SGerd Hoffmann DEFINE_PROP_SIZE("membar", PCITestDevState, membar_size, 0), 32741746334SGerd Hoffmann DEFINE_PROP_END_OF_LIST(), 32841746334SGerd Hoffmann }; 32941746334SGerd Hoffmann 33022773d60SMichael S. Tsirkin static void pci_testdev_class_init(ObjectClass *klass, void *data) 33122773d60SMichael S. Tsirkin { 33222773d60SMichael S. Tsirkin DeviceClass *dc = DEVICE_CLASS(klass); 33322773d60SMichael S. Tsirkin PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 33422773d60SMichael S. Tsirkin 3359af21dbeSMarkus Armbruster k->realize = pci_testdev_realize; 33622773d60SMichael S. Tsirkin k->exit = pci_testdev_uninit; 33722773d60SMichael S. Tsirkin k->vendor_id = PCI_VENDOR_ID_REDHAT; 33822773d60SMichael S. Tsirkin k->device_id = PCI_DEVICE_ID_REDHAT_TEST; 33922773d60SMichael S. Tsirkin k->revision = 0x00; 34022773d60SMichael S. Tsirkin k->class_id = PCI_CLASS_OTHERS; 34122773d60SMichael S. Tsirkin dc->desc = "PCI Test Device"; 342125ee0edSMarcel Apfelbaum set_bit(DEVICE_CATEGORY_MISC, dc->categories); 34322773d60SMichael S. Tsirkin dc->reset = qdev_pci_testdev_reset; 3444f67d30bSMarc-André Lureau device_class_set_props(dc, pci_testdev_properties); 34522773d60SMichael S. Tsirkin } 34622773d60SMichael S. Tsirkin 34722773d60SMichael S. Tsirkin static const TypeInfo pci_testdev_info = { 34840108d0aSPeter Crosthwaite .name = TYPE_PCI_TEST_DEV, 34922773d60SMichael S. Tsirkin .parent = TYPE_PCI_DEVICE, 35022773d60SMichael S. Tsirkin .instance_size = sizeof(PCITestDevState), 35122773d60SMichael S. Tsirkin .class_init = pci_testdev_class_init, 352fd3b02c8SEduardo Habkost .interfaces = (InterfaceInfo[]) { 353fd3b02c8SEduardo Habkost { INTERFACE_CONVENTIONAL_PCI_DEVICE }, 354fd3b02c8SEduardo Habkost { }, 355fd3b02c8SEduardo Habkost }, 35622773d60SMichael S. Tsirkin }; 35722773d60SMichael S. Tsirkin 35822773d60SMichael S. Tsirkin static void pci_testdev_register_types(void) 35922773d60SMichael S. Tsirkin { 36022773d60SMichael S. Tsirkin type_register_static(&pci_testdev_info); 36122773d60SMichael S. Tsirkin } 36222773d60SMichael S. Tsirkin 36322773d60SMichael S. Tsirkin type_init(pci_testdev_register_types) 364