xref: /qemu/hw/nubus/nubus-virtio-mmio.c (revision 3e775730)
1 /*
2  * QEMU Macintosh Nubus Virtio MMIO card
3  *
4  * Copyright (c) 2024 Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
5  *
6  * SPDX-License-Identifier: GPL-2.0-or-later
7  */
8 
9 #include "qemu/osdep.h"
10 #include "hw/nubus/nubus-virtio-mmio.h"
11 
12 
13 #define NUBUS_VIRTIO_MMIO_PIC_OFFSET   0
14 #define NUBUS_VIRTIO_MMIO_DEV_OFFSET   0x200
15 
16 
17 static void nubus_virtio_mmio_set_input_irq(void *opaque, int n, int level)
18 {
19     NubusDevice *nd = NUBUS_DEVICE(opaque);
20 
21     nubus_set_irq(nd, level);
22 }
23 
24 static void nubus_virtio_mmio_realize(DeviceState *dev, Error **errp)
25 {
26     NubusVirtioMMIODeviceClass *nvmdc = NUBUS_VIRTIO_MMIO_GET_CLASS(dev);
27     NubusVirtioMMIO *s = NUBUS_VIRTIO_MMIO(dev);
28     NubusDevice *nd = NUBUS_DEVICE(dev);
29     SysBusDevice *sbd;
30     int i, offset;
31 
32     nvmdc->parent_realize(dev, errp);
33     if (*errp) {
34         return;
35     }
36 
37     /* Goldfish PIC */
38     sbd = SYS_BUS_DEVICE(&s->pic);
39     if (!sysbus_realize(sbd, errp)) {
40         return;
41     }
42     memory_region_add_subregion(&nd->slot_mem, NUBUS_VIRTIO_MMIO_PIC_OFFSET,
43                                 sysbus_mmio_get_region(sbd, 0));
44     sysbus_connect_irq(sbd, 0,
45                        qdev_get_gpio_in_named(dev, "pic-input-irq", 0));
46 
47     /* virtio-mmio devices */
48     offset = NUBUS_VIRTIO_MMIO_DEV_OFFSET;
49     for (i = 0; i < NUBUS_VIRTIO_MMIO_NUM_DEVICES; i++) {
50         sbd = SYS_BUS_DEVICE(&s->virtio_mmio[i]);
51         qdev_prop_set_bit(DEVICE(sbd), "force-legacy", false);
52         if (!sysbus_realize_and_unref(sbd, errp)) {
53             return;
54         }
55 
56         memory_region_add_subregion(&nd->slot_mem, offset,
57                                     sysbus_mmio_get_region(sbd, 0));
58         offset += 0x200;
59 
60         sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(DEVICE(&s->pic), i));
61     }
62 }
63 
64 static void nubus_virtio_mmio_init(Object *obj)
65 {
66     NubusVirtioMMIO *s = NUBUS_VIRTIO_MMIO(obj);
67     int i;
68 
69     object_initialize_child(obj, "pic", &s->pic, TYPE_GOLDFISH_PIC);
70     for (i = 0; i < NUBUS_VIRTIO_MMIO_NUM_DEVICES; i++) {
71         char *name = g_strdup_printf("virtio-mmio[%d]", i);
72         object_initialize_child(obj, name, &s->virtio_mmio[i],
73                                 TYPE_VIRTIO_MMIO);
74         g_free(name);
75     }
76 
77     /* Input from goldfish PIC */
78     qdev_init_gpio_in_named(DEVICE(obj), nubus_virtio_mmio_set_input_irq,
79                             "pic-input-irq", 1);
80 }
81 
82 static void nubus_virtio_mmio_class_init(ObjectClass *oc, void *data)
83 {
84     DeviceClass *dc = DEVICE_CLASS(oc);
85     NubusVirtioMMIODeviceClass *nvmdc = NUBUS_VIRTIO_MMIO_CLASS(oc);
86 
87     device_class_set_parent_realize(dc, nubus_virtio_mmio_realize,
88                                     &nvmdc->parent_realize);
89 }
90 
91 static const TypeInfo nubus_virtio_mmio_types[] = {
92     {
93         .name = TYPE_NUBUS_VIRTIO_MMIO,
94         .parent = TYPE_NUBUS_DEVICE,
95         .instance_init = nubus_virtio_mmio_init,
96         .instance_size = sizeof(NubusVirtioMMIO),
97         .class_init = nubus_virtio_mmio_class_init,
98         .class_size = sizeof(NubusVirtioMMIODeviceClass),
99     },
100 };
101 
102 DEFINE_TYPES(nubus_virtio_mmio_types)
103