]>
Commit | Line | Data |
---|---|---|
da9fcfa5 AT |
1 | /* |
2 | * QEMU Empty Slot | |
3 | * | |
4 | * The empty_slot device emulates known to a bus but not connected devices. | |
5 | * | |
6 | * Copyright (c) 2010 Artyom Tarasenko | |
7 | * | |
8 | * This code is licensed under the GNU GPL v2 or (at your option) any later | |
9 | * version. | |
10 | */ | |
11 | ||
18c86e2b | 12 | #include "qemu/osdep.h" |
83c9f4ca | 13 | #include "hw/sysbus.h" |
4bbadef0 | 14 | #include "hw/qdev-properties.h" |
6007523a | 15 | #include "hw/misc/empty_slot.h" |
c0e43084 | 16 | #include "trace.h" |
da9fcfa5 | 17 | |
8df81c4b AF |
18 | #define TYPE_EMPTY_SLOT "empty_slot" |
19 | #define EMPTY_SLOT(obj) OBJECT_CHECK(EmptySlot, (obj), TYPE_EMPTY_SLOT) | |
20 | ||
da9fcfa5 | 21 | typedef struct EmptySlot { |
8df81c4b AF |
22 | SysBusDevice parent_obj; |
23 | ||
b0a941b0 | 24 | MemoryRegion iomem; |
07ddf5cb | 25 | char *name; |
da9fcfa5 AT |
26 | uint64_t size; |
27 | } EmptySlot; | |
28 | ||
a8170e5e | 29 | static uint64_t empty_slot_read(void *opaque, hwaddr addr, |
b0a941b0 | 30 | unsigned size) |
da9fcfa5 | 31 | { |
c0e43084 PMD |
32 | EmptySlot *s = EMPTY_SLOT(opaque); |
33 | ||
34 | trace_empty_slot_write(addr, size << 1, 0, size, s->name); | |
35 | ||
da9fcfa5 AT |
36 | return 0; |
37 | } | |
38 | ||
a8170e5e | 39 | static void empty_slot_write(void *opaque, hwaddr addr, |
b0a941b0 | 40 | uint64_t val, unsigned size) |
da9fcfa5 | 41 | { |
c0e43084 PMD |
42 | EmptySlot *s = EMPTY_SLOT(opaque); |
43 | ||
44 | trace_empty_slot_write(addr, size << 1, val, size, s->name); | |
da9fcfa5 AT |
45 | } |
46 | ||
b0a941b0 AK |
47 | static const MemoryRegionOps empty_slot_ops = { |
48 | .read = empty_slot_read, | |
49 | .write = empty_slot_write, | |
50 | .endianness = DEVICE_NATIVE_ENDIAN, | |
da9fcfa5 AT |
51 | }; |
52 | ||
a8170e5e | 53 | void empty_slot_init(hwaddr addr, uint64_t slot_size) |
da9fcfa5 | 54 | { |
1a00282a SW |
55 | if (slot_size > 0) { |
56 | /* Only empty slots larger than 0 byte need handling. */ | |
57 | DeviceState *dev; | |
da9fcfa5 | 58 | |
8df81c4b | 59 | dev = qdev_create(NULL, TYPE_EMPTY_SLOT); |
da9fcfa5 | 60 | |
4bbadef0 | 61 | qdev_prop_set_uint64(dev, "size", slot_size); |
1a00282a | 62 | qdev_init_nofail(dev); |
da9fcfa5 | 63 | |
4bbadef0 | 64 | sysbus_mmio_map_overlap(SYS_BUS_DEVICE(dev), 0, addr, -10000); |
1a00282a | 65 | } |
da9fcfa5 AT |
66 | } |
67 | ||
4dbf209d | 68 | static void empty_slot_realize(DeviceState *dev, Error **errp) |
da9fcfa5 | 69 | { |
8df81c4b | 70 | EmptySlot *s = EMPTY_SLOT(dev); |
da9fcfa5 | 71 | |
07ddf5cb PMD |
72 | if (s->name == NULL) { |
73 | s->name = g_strdup("empty-slot"); | |
74 | } | |
300b1fc6 | 75 | memory_region_init_io(&s->iomem, OBJECT(s), &empty_slot_ops, s, |
07ddf5cb | 76 | s->name, s->size); |
4dbf209d | 77 | sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem); |
da9fcfa5 AT |
78 | } |
79 | ||
4bbadef0 PMD |
80 | static Property empty_slot_properties[] = { |
81 | DEFINE_PROP_UINT64("size", EmptySlot, size, 0), | |
07ddf5cb | 82 | DEFINE_PROP_STRING("name", EmptySlot, name), |
4bbadef0 PMD |
83 | DEFINE_PROP_END_OF_LIST(), |
84 | }; | |
85 | ||
999e12bb AL |
86 | static void empty_slot_class_init(ObjectClass *klass, void *data) |
87 | { | |
4dbf209d | 88 | DeviceClass *dc = DEVICE_CLASS(klass); |
999e12bb | 89 | |
4dbf209d | 90 | dc->realize = empty_slot_realize; |
4bbadef0 | 91 | device_class_set_props(dc, empty_slot_properties); |
6007523a | 92 | set_bit(DEVICE_CATEGORY_MISC, dc->categories); |
999e12bb AL |
93 | } |
94 | ||
8c43a6f0 | 95 | static const TypeInfo empty_slot_info = { |
8df81c4b | 96 | .name = TYPE_EMPTY_SLOT, |
39bffca2 AL |
97 | .parent = TYPE_SYS_BUS_DEVICE, |
98 | .instance_size = sizeof(EmptySlot), | |
99 | .class_init = empty_slot_class_init, | |
da9fcfa5 AT |
100 | }; |
101 | ||
83f7d43a | 102 | static void empty_slot_register_types(void) |
da9fcfa5 | 103 | { |
39bffca2 | 104 | type_register_static(&empty_slot_info); |
da9fcfa5 AT |
105 | } |
106 | ||
83f7d43a | 107 | type_init(empty_slot_register_types) |