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 | |
12 | #include "qemu/osdep.h" |
13 | #include "hw/sysbus.h" |
14 | #include "qemu/module.h" |
15 | #include "hw/empty_slot.h" |
16 | |
17 | //#define DEBUG_EMPTY_SLOT |
18 | |
19 | #ifdef DEBUG_EMPTY_SLOT |
20 | #define DPRINTF(fmt, ...) \ |
21 | do { printf("empty_slot: " fmt , ## __VA_ARGS__); } while (0) |
22 | #else |
23 | #define DPRINTF(fmt, ...) do {} while (0) |
24 | #endif |
25 | |
26 | #define TYPE_EMPTY_SLOT "empty_slot" |
27 | #define EMPTY_SLOT(obj) OBJECT_CHECK(EmptySlot, (obj), TYPE_EMPTY_SLOT) |
28 | |
29 | typedef struct EmptySlot { |
30 | SysBusDevice parent_obj; |
31 | |
32 | MemoryRegion iomem; |
33 | uint64_t size; |
34 | } EmptySlot; |
35 | |
36 | static uint64_t empty_slot_read(void *opaque, hwaddr addr, |
37 | unsigned size) |
38 | { |
39 | DPRINTF("read from " TARGET_FMT_plx "\n" , addr); |
40 | return 0; |
41 | } |
42 | |
43 | static void empty_slot_write(void *opaque, hwaddr addr, |
44 | uint64_t val, unsigned size) |
45 | { |
46 | DPRINTF("write 0x%x to " TARGET_FMT_plx "\n" , (unsigned)val, addr); |
47 | } |
48 | |
49 | static const MemoryRegionOps empty_slot_ops = { |
50 | .read = empty_slot_read, |
51 | .write = empty_slot_write, |
52 | .endianness = DEVICE_NATIVE_ENDIAN, |
53 | }; |
54 | |
55 | void empty_slot_init(hwaddr addr, uint64_t slot_size) |
56 | { |
57 | if (slot_size > 0) { |
58 | /* Only empty slots larger than 0 byte need handling. */ |
59 | DeviceState *dev; |
60 | SysBusDevice *s; |
61 | EmptySlot *e; |
62 | |
63 | dev = qdev_create(NULL, TYPE_EMPTY_SLOT); |
64 | s = SYS_BUS_DEVICE(dev); |
65 | e = EMPTY_SLOT(dev); |
66 | e->size = slot_size; |
67 | |
68 | qdev_init_nofail(dev); |
69 | |
70 | sysbus_mmio_map(s, 0, addr); |
71 | } |
72 | } |
73 | |
74 | static void empty_slot_realize(DeviceState *dev, Error **errp) |
75 | { |
76 | EmptySlot *s = EMPTY_SLOT(dev); |
77 | |
78 | memory_region_init_io(&s->iomem, OBJECT(s), &empty_slot_ops, s, |
79 | "empty-slot" , s->size); |
80 | sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem); |
81 | } |
82 | |
83 | static void empty_slot_class_init(ObjectClass *klass, void *data) |
84 | { |
85 | DeviceClass *dc = DEVICE_CLASS(klass); |
86 | |
87 | dc->realize = empty_slot_realize; |
88 | } |
89 | |
90 | static const TypeInfo empty_slot_info = { |
91 | .name = TYPE_EMPTY_SLOT, |
92 | .parent = TYPE_SYS_BUS_DEVICE, |
93 | .instance_size = sizeof(EmptySlot), |
94 | .class_init = empty_slot_class_init, |
95 | }; |
96 | |
97 | static void empty_slot_register_types(void) |
98 | { |
99 | type_register_static(&empty_slot_info); |
100 | } |
101 | |
102 | type_init(empty_slot_register_types) |
103 | |