xref: /qemu/hw/misc/empty_slot.c (revision 07ddf5cbe2e9499cc2d238e5c864ac3f5bdd25ce)
1da9fcfa5SArtyom Tarasenko /*
2da9fcfa5SArtyom Tarasenko  * QEMU Empty Slot
3da9fcfa5SArtyom Tarasenko  *
4da9fcfa5SArtyom Tarasenko  * The empty_slot device emulates known to a bus but not connected devices.
5da9fcfa5SArtyom Tarasenko  *
6da9fcfa5SArtyom Tarasenko  * Copyright (c) 2010 Artyom Tarasenko
7da9fcfa5SArtyom Tarasenko  *
8da9fcfa5SArtyom Tarasenko  * This code is licensed under the GNU GPL v2 or (at your option) any later
9da9fcfa5SArtyom Tarasenko  * version.
10da9fcfa5SArtyom Tarasenko  */
11da9fcfa5SArtyom Tarasenko 
1218c86e2bSPeter Maydell #include "qemu/osdep.h"
1383c9f4caSPaolo Bonzini #include "hw/sysbus.h"
140b8fa32fSMarkus Armbruster #include "qemu/module.h"
154bbadef0SPhilippe Mathieu-Daudé #include "hw/qdev-properties.h"
1683c9f4caSPaolo Bonzini #include "hw/empty_slot.h"
17da9fcfa5SArtyom Tarasenko 
18da9fcfa5SArtyom Tarasenko //#define DEBUG_EMPTY_SLOT
19da9fcfa5SArtyom Tarasenko 
20da9fcfa5SArtyom Tarasenko #ifdef DEBUG_EMPTY_SLOT
21da9fcfa5SArtyom Tarasenko #define DPRINTF(fmt, ...)                                       \
22da9fcfa5SArtyom Tarasenko     do { printf("empty_slot: " fmt , ## __VA_ARGS__); } while (0)
23da9fcfa5SArtyom Tarasenko #else
24da9fcfa5SArtyom Tarasenko #define DPRINTF(fmt, ...) do {} while (0)
25da9fcfa5SArtyom Tarasenko #endif
26da9fcfa5SArtyom Tarasenko 
278df81c4bSAndreas Färber #define TYPE_EMPTY_SLOT "empty_slot"
288df81c4bSAndreas Färber #define EMPTY_SLOT(obj) OBJECT_CHECK(EmptySlot, (obj), TYPE_EMPTY_SLOT)
298df81c4bSAndreas Färber 
30da9fcfa5SArtyom Tarasenko typedef struct EmptySlot {
318df81c4bSAndreas Färber     SysBusDevice parent_obj;
328df81c4bSAndreas Färber 
33b0a941b0SAvi Kivity     MemoryRegion iomem;
34*07ddf5cbSPhilippe Mathieu-Daudé     char *name;
35da9fcfa5SArtyom Tarasenko     uint64_t size;
36da9fcfa5SArtyom Tarasenko } EmptySlot;
37da9fcfa5SArtyom Tarasenko 
38a8170e5eSAvi Kivity static uint64_t empty_slot_read(void *opaque, hwaddr addr,
39b0a941b0SAvi Kivity                                 unsigned size)
40da9fcfa5SArtyom Tarasenko {
41da9fcfa5SArtyom Tarasenko     DPRINTF("read from " TARGET_FMT_plx "\n", addr);
42da9fcfa5SArtyom Tarasenko     return 0;
43da9fcfa5SArtyom Tarasenko }
44da9fcfa5SArtyom Tarasenko 
45a8170e5eSAvi Kivity static void empty_slot_write(void *opaque, hwaddr addr,
46b0a941b0SAvi Kivity                              uint64_t val, unsigned size)
47da9fcfa5SArtyom Tarasenko {
48b0a941b0SAvi Kivity     DPRINTF("write 0x%x to " TARGET_FMT_plx "\n", (unsigned)val, addr);
49da9fcfa5SArtyom Tarasenko }
50da9fcfa5SArtyom Tarasenko 
51b0a941b0SAvi Kivity static const MemoryRegionOps empty_slot_ops = {
52b0a941b0SAvi Kivity     .read = empty_slot_read,
53b0a941b0SAvi Kivity     .write = empty_slot_write,
54b0a941b0SAvi Kivity     .endianness = DEVICE_NATIVE_ENDIAN,
55da9fcfa5SArtyom Tarasenko };
56da9fcfa5SArtyom Tarasenko 
57a8170e5eSAvi Kivity void empty_slot_init(hwaddr addr, uint64_t slot_size)
58da9fcfa5SArtyom Tarasenko {
591a00282aSStefan Weil     if (slot_size > 0) {
601a00282aSStefan Weil         /* Only empty slots larger than 0 byte need handling. */
61da9fcfa5SArtyom Tarasenko         DeviceState *dev;
62da9fcfa5SArtyom Tarasenko 
638df81c4bSAndreas Färber         dev = qdev_create(NULL, TYPE_EMPTY_SLOT);
64da9fcfa5SArtyom Tarasenko 
654bbadef0SPhilippe Mathieu-Daudé         qdev_prop_set_uint64(dev, "size", slot_size);
66da9fcfa5SArtyom Tarasenko         qdev_init_nofail(dev);
67da9fcfa5SArtyom Tarasenko 
684bbadef0SPhilippe Mathieu-Daudé         sysbus_mmio_map_overlap(SYS_BUS_DEVICE(dev), 0, addr, -10000);
69da9fcfa5SArtyom Tarasenko     }
701a00282aSStefan Weil }
71da9fcfa5SArtyom Tarasenko 
724dbf209dSMao Zhongyi static void empty_slot_realize(DeviceState *dev, Error **errp)
73da9fcfa5SArtyom Tarasenko {
748df81c4bSAndreas Färber     EmptySlot *s = EMPTY_SLOT(dev);
75da9fcfa5SArtyom Tarasenko 
76*07ddf5cbSPhilippe Mathieu-Daudé     if (s->name == NULL) {
77*07ddf5cbSPhilippe Mathieu-Daudé         s->name = g_strdup("empty-slot");
78*07ddf5cbSPhilippe Mathieu-Daudé     }
79300b1fc6SPaolo Bonzini     memory_region_init_io(&s->iomem, OBJECT(s), &empty_slot_ops, s,
80*07ddf5cbSPhilippe Mathieu-Daudé                           s->name, s->size);
814dbf209dSMao Zhongyi     sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
82da9fcfa5SArtyom Tarasenko }
83da9fcfa5SArtyom Tarasenko 
844bbadef0SPhilippe Mathieu-Daudé static Property empty_slot_properties[] = {
854bbadef0SPhilippe Mathieu-Daudé     DEFINE_PROP_UINT64("size", EmptySlot, size, 0),
86*07ddf5cbSPhilippe Mathieu-Daudé     DEFINE_PROP_STRING("name", EmptySlot, name),
874bbadef0SPhilippe Mathieu-Daudé     DEFINE_PROP_END_OF_LIST(),
884bbadef0SPhilippe Mathieu-Daudé };
894bbadef0SPhilippe Mathieu-Daudé 
90999e12bbSAnthony Liguori static void empty_slot_class_init(ObjectClass *klass, void *data)
91999e12bbSAnthony Liguori {
924dbf209dSMao Zhongyi     DeviceClass *dc = DEVICE_CLASS(klass);
93999e12bbSAnthony Liguori 
944dbf209dSMao Zhongyi     dc->realize = empty_slot_realize;
954bbadef0SPhilippe Mathieu-Daudé     device_class_set_props(dc, empty_slot_properties);
96999e12bbSAnthony Liguori }
97999e12bbSAnthony Liguori 
988c43a6f0SAndreas Färber static const TypeInfo empty_slot_info = {
998df81c4bSAndreas Färber     .name          = TYPE_EMPTY_SLOT,
10039bffca2SAnthony Liguori     .parent        = TYPE_SYS_BUS_DEVICE,
10139bffca2SAnthony Liguori     .instance_size = sizeof(EmptySlot),
102999e12bbSAnthony Liguori     .class_init    = empty_slot_class_init,
103da9fcfa5SArtyom Tarasenko };
104da9fcfa5SArtyom Tarasenko 
10583f7d43aSAndreas Färber static void empty_slot_register_types(void)
106da9fcfa5SArtyom Tarasenko {
10739bffca2SAnthony Liguori     type_register_static(&empty_slot_info);
108da9fcfa5SArtyom Tarasenko }
109da9fcfa5SArtyom Tarasenko 
11083f7d43aSAndreas Färber type_init(empty_slot_register_types)
111