1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include "qemu/osdep.h"
21#include "hw/sysbus.h"
22#include "monitor/monitor.h"
23#include "exec/address-spaces.h"
24
25#include "hw/fdt_generic_util.h"
26
27static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent);
28static char *sysbus_get_fw_dev_path(DeviceState *dev);
29
30typedef struct SysBusFind {
31 void *opaque;
32 FindSysbusDeviceFunc *func;
33} SysBusFind;
34
35
36static int find_sysbus_device(Object *obj, void *opaque)
37{
38 SysBusFind *find = opaque;
39 Object *dev;
40 SysBusDevice *sbdev;
41
42 dev = object_dynamic_cast(obj, TYPE_SYS_BUS_DEVICE);
43 sbdev = (SysBusDevice *)dev;
44
45 if (!sbdev) {
46
47 return object_child_foreach(obj, find_sysbus_device, opaque);
48 }
49
50 find->func(sbdev, find->opaque);
51
52 return 0;
53}
54
55
56
57
58
59void foreach_dynamic_sysbus_device(FindSysbusDeviceFunc *func, void *opaque)
60{
61 Object *container;
62 SysBusFind find = {
63 .func = func,
64 .opaque = opaque,
65 };
66
67
68 container = container_get(qdev_get_machine(), "/peripheral");
69 find_sysbus_device(container, &find);
70 container = container_get(qdev_get_machine(), "/peripheral-anon");
71 find_sysbus_device(container, &find);
72}
73
74
75static void system_bus_class_init(ObjectClass *klass, void *data)
76{
77 BusClass *k = BUS_CLASS(klass);
78
79 k->print_dev = sysbus_dev_print;
80 k->get_fw_dev_path = sysbus_get_fw_dev_path;
81}
82
83static const TypeInfo system_bus_info = {
84 .name = TYPE_SYSTEM_BUS,
85 .parent = TYPE_BUS,
86 .instance_size = sizeof(BusState),
87 .class_init = system_bus_class_init,
88};
89
90
91bool sysbus_has_irq(SysBusDevice *dev, int n)
92{
93 char *prop = g_strdup_printf("%s[%d]", SYSBUS_DEVICE_GPIO_IRQ, n);
94 ObjectProperty *r;
95
96 r = object_property_find(OBJECT(dev), prop, NULL);
97 g_free(prop);
98
99 return (r != NULL);
100}
101
102bool sysbus_is_irq_connected(SysBusDevice *dev, int n)
103{
104 return !!sysbus_get_connected_irq(dev, n);
105}
106
107qemu_irq sysbus_get_connected_irq(SysBusDevice *dev, int n)
108{
109 DeviceState *d = DEVICE(dev);
110 return qdev_get_gpio_out_connector(d, SYSBUS_DEVICE_GPIO_IRQ, n);
111}
112
113void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq)
114{
115 SysBusDeviceClass *sbd = SYS_BUS_DEVICE_GET_CLASS(dev);
116
117 qdev_connect_gpio_out_named(DEVICE(dev), SYSBUS_DEVICE_GPIO_IRQ, n, irq);
118
119 if (sbd->connect_irq_notifier) {
120 sbd->connect_irq_notifier(dev, irq);
121 }
122}
123
124
125bool sysbus_has_mmio(SysBusDevice *dev, unsigned int n)
126{
127 return (n < dev->num_mmio);
128}
129
130static void sysbus_mmio_map_common(SysBusDevice *dev, int n, hwaddr addr,
131 bool may_overlap, int priority)
132{
133 assert(n >= 0 && n < dev->num_mmio);
134
135 if (dev->mmio[n].addr == addr) {
136
137 return;
138 }
139 if (dev->mmio[n].addr != (hwaddr)-1) {
140
141 memory_region_del_subregion(get_system_memory(), dev->mmio[n].memory);
142 }
143 dev->mmio[n].addr = addr;
144 if (may_overlap) {
145 memory_region_add_subregion_overlap(get_system_memory(),
146 addr,
147 dev->mmio[n].memory,
148 priority);
149 }
150 else {
151 memory_region_add_subregion(get_system_memory(),
152 addr,
153 dev->mmio[n].memory);
154 }
155}
156
157void sysbus_mmio_map(SysBusDevice *dev, int n, hwaddr addr)
158{
159 sysbus_mmio_map_common(dev, n, addr, false, 0);
160}
161
162void sysbus_mmio_map_overlap(SysBusDevice *dev, int n, hwaddr addr,
163 int priority)
164{
165 sysbus_mmio_map_common(dev, n, addr, true, priority);
166}
167
168
169void sysbus_init_irq(SysBusDevice *dev, qemu_irq *p)
170{
171 qdev_init_gpio_out_named(DEVICE(dev), p, SYSBUS_DEVICE_GPIO_IRQ, 1);
172}
173
174
175void sysbus_pass_irq(SysBusDevice *dev, SysBusDevice *target)
176{
177 qdev_pass_gpios(DEVICE(target), DEVICE(dev), SYSBUS_DEVICE_GPIO_IRQ);
178}
179
180void sysbus_init_mmio(SysBusDevice *dev, MemoryRegion *memory)
181{
182 int n;
183
184 assert(dev->num_mmio < QDEV_MAX_MMIO);
185 n = dev->num_mmio++;
186 dev->mmio[n].addr = -1;
187 dev->mmio[n].memory = memory;
188}
189
190MemoryRegion *sysbus_mmio_get_region(SysBusDevice *dev, int n)
191{
192 return dev->mmio[n].memory;
193}
194
195void sysbus_init_ioports(SysBusDevice *dev, uint32_t ioport, uint32_t size)
196{
197 uint32_t i;
198
199 for (i = 0; i < size; i++) {
200 assert(dev->num_pio < QDEV_MAX_PIO);
201 dev->pio[dev->num_pio++] = ioport++;
202 }
203}
204
205static int sysbus_device_init(DeviceState *dev)
206{
207 SysBusDevice *sd = SYS_BUS_DEVICE(dev);
208 SysBusDeviceClass *sbc = SYS_BUS_DEVICE_GET_CLASS(sd);
209
210 if (!sbc->init) {
211 return 0;
212 }
213 return sbc->init(sd);
214}
215
216DeviceState *sysbus_create_varargs(const char *name,
217 hwaddr addr, ...)
218{
219 DeviceState *dev;
220 SysBusDevice *s;
221 va_list va;
222 qemu_irq irq;
223 int n;
224
225 dev = qdev_create(NULL, name);
226 s = SYS_BUS_DEVICE(dev);
227 qdev_init_nofail(dev);
228 if (addr != (hwaddr)-1) {
229 sysbus_mmio_map(s, 0, addr);
230 }
231 va_start(va, addr);
232 n = 0;
233 while (1) {
234 irq = va_arg(va, qemu_irq);
235 if (!irq) {
236 break;
237 }
238 sysbus_connect_irq(s, n, irq);
239 n++;
240 }
241 va_end(va);
242 return dev;
243}
244
245DeviceState *sysbus_try_create_varargs(const char *name,
246 hwaddr addr, ...)
247{
248 DeviceState *dev;
249 SysBusDevice *s;
250 va_list va;
251 qemu_irq irq;
252 int n;
253
254 dev = qdev_try_create(NULL, name);
255 if (!dev) {
256 return NULL;
257 }
258 s = SYS_BUS_DEVICE(dev);
259 qdev_init_nofail(dev);
260 if (addr != (hwaddr)-1) {
261 sysbus_mmio_map(s, 0, addr);
262 }
263 va_start(va, addr);
264 n = 0;
265 while (1) {
266 irq = va_arg(va, qemu_irq);
267 if (!irq) {
268 break;
269 }
270 sysbus_connect_irq(s, n, irq);
271 n++;
272 }
273 va_end(va);
274 return dev;
275}
276
277static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent)
278{
279 SysBusDevice *s = SYS_BUS_DEVICE(dev);
280 hwaddr size;
281 int i;
282
283 for (i = 0; i < s->num_mmio; i++) {
284 size = memory_region_size(s->mmio[i].memory);
285 monitor_printf(mon, "%*smmio " TARGET_FMT_plx "/" TARGET_FMT_plx "\n",
286 indent, "", s->mmio[i].addr, size);
287 }
288}
289
290static char *sysbus_get_fw_dev_path(DeviceState *dev)
291{
292 SysBusDevice *s = SYS_BUS_DEVICE(dev);
293 SysBusDeviceClass *sbc = SYS_BUS_DEVICE_GET_CLASS(s);
294
295 char *addr, *fw_dev_path;
296
297 if (s->num_mmio) {
298 return g_strdup_printf("%s@" TARGET_FMT_plx, qdev_fw_name(dev),
299 s->mmio[0].addr);
300 }
301 if (s->num_pio) {
302 return g_strdup_printf("%s@i%04x", qdev_fw_name(dev), s->pio[0]);
303 }
304 if (sbc->explicit_ofw_unit_address) {
305 addr = sbc->explicit_ofw_unit_address(s);
306 if (addr) {
307 fw_dev_path = g_strdup_printf("%s@%s", qdev_fw_name(dev), addr);
308 g_free(addr);
309 return fw_dev_path;
310 }
311 }
312 return g_strdup(qdev_fw_name(dev));
313}
314
315void sysbus_add_io(SysBusDevice *dev, hwaddr addr,
316 MemoryRegion *mem)
317{
318 memory_region_add_subregion(get_system_io(), addr, mem);
319}
320
321MemoryRegion *sysbus_address_space(SysBusDevice *dev)
322{
323 return get_system_memory();
324}
325
326static bool sysbus_parse_reg(FDTGenericMMap *obj, FDTGenericRegPropInfo reg,
327 Error **errp) {
328 int i;
329
330 for (i = 0; i < reg.n; ++i) {
331 MemoryRegion *mr_parent = (MemoryRegion *)
332 object_dynamic_cast(reg.parents[i], TYPE_MEMORY_REGION);
333 if (!mr_parent) {
334
335 mr_parent = get_system_memory();
336 }
337 memory_region_add_subregion_overlap(mr_parent, reg.a[i],
338 sysbus_mmio_get_region(SYS_BUS_DEVICE(obj), i),
339 reg.p[i]);
340 }
341 return false;
342}
343
344static void sysbus_device_pwr_hlt_cntrl(void *opaque)
345{
346 DeviceState *dev = DEVICE(opaque);
347 SysBusDevice *s = SYS_BUS_DEVICE(opaque);
348 int i;
349
350 for (i = 0;; i++) {
351 MemoryRegion *mr = sysbus_mmio_get_region(s, i);
352 if (!mr) {
353 break;
354 }
355 memory_region_set_enabled(mr, dev->ps.active);
356 }
357}
358static void sysbus_device_pwr_cntrl(void *opaque, int n, int level)
359{
360 DeviceClass *dc_parent = DEVICE_CLASS(SYS_BUS_DEVICE_PARENT_CLASS);
361
362 dc_parent->pwr_cntrl(opaque, n, level);
363 sysbus_device_pwr_hlt_cntrl(opaque);
364}
365
366static void sysbus_device_hlt_cntrl(void *opaque, int n, int level)
367{
368 DeviceClass *dc_parent = DEVICE_CLASS(SYS_BUS_DEVICE_PARENT_CLASS);
369
370 dc_parent->hlt_cntrl(opaque, n, level);
371 sysbus_device_pwr_hlt_cntrl(opaque);
372}
373
374static void sysbus_device_class_init(ObjectClass *klass, void *data)
375{
376 DeviceClass *k = DEVICE_CLASS(klass);
377 FDTGenericMMapClass *fmc = FDT_GENERIC_MMAP_CLASS(klass);
378
379 k->init = sysbus_device_init;
380 k->bus_type = TYPE_SYSTEM_BUS;
381 k->pwr_cntrl = sysbus_device_pwr_cntrl;
382 k->hlt_cntrl = sysbus_device_hlt_cntrl;
383 fmc->parse_reg = sysbus_parse_reg;
384
385
386
387
388
389
390
391
392
393
394 k->user_creatable = false;
395}
396
397static const TypeInfo sysbus_device_type_info = {
398 .name = TYPE_SYS_BUS_DEVICE,
399 .parent = TYPE_DEVICE,
400 .instance_size = sizeof(SysBusDevice),
401 .abstract = true,
402 .class_size = sizeof(SysBusDeviceClass),
403 .class_init = sysbus_device_class_init,
404 .interfaces = (InterfaceInfo[]) {
405 { TYPE_FDT_GENERIC_MMAP },
406 { },
407 },
408};
409
410
411static BusState *main_system_bus;
412
413static void main_system_bus_create(void)
414{
415
416
417 main_system_bus = g_malloc0(system_bus_info.instance_size);
418 qbus_create_inplace(main_system_bus, system_bus_info.instance_size,
419 TYPE_SYSTEM_BUS, NULL, "main-system-bus");
420 OBJECT(main_system_bus)->free = g_free;
421 object_property_add_child(container_get(qdev_get_machine(),
422 "/unattached"),
423 "sysbus", OBJECT(main_system_bus), NULL);
424}
425
426BusState *sysbus_get_default(void)
427{
428 if (!main_system_bus) {
429 main_system_bus_create();
430 }
431 return main_system_bus;
432}
433
434static void sysbus_register_types(void)
435{
436 type_register_static(&system_bus_info);
437 type_register_static(&sysbus_device_type_info);
438}
439
440type_init(sysbus_register_types)
441