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