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