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