xref: /qemu/hw/nubus/nubus-virtio-mmio.c (revision e4751d340a49b117b90a411b179b8c892cf43d85)
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