131ae8bb1SMark Cave-Ayland /* 231ae8bb1SMark Cave-Ayland * QEMU Macintosh Nubus Virtio MMIO card 331ae8bb1SMark Cave-Ayland * 431ae8bb1SMark Cave-Ayland * Copyright (c) 2024 Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> 531ae8bb1SMark Cave-Ayland * 631ae8bb1SMark Cave-Ayland * SPDX-License-Identifier: GPL-2.0-or-later 731ae8bb1SMark Cave-Ayland */ 831ae8bb1SMark Cave-Ayland 931ae8bb1SMark Cave-Ayland #include "qemu/osdep.h" 102f28f28eSZhao Liu #include "qapi/error.h" 1131ae8bb1SMark Cave-Ayland #include "hw/nubus/nubus-virtio-mmio.h" 1231ae8bb1SMark Cave-Ayland 1331ae8bb1SMark Cave-Ayland 1431ae8bb1SMark Cave-Ayland #define NUBUS_VIRTIO_MMIO_PIC_OFFSET 0 1531ae8bb1SMark Cave-Ayland #define NUBUS_VIRTIO_MMIO_DEV_OFFSET 0x200 1631ae8bb1SMark Cave-Ayland 1731ae8bb1SMark Cave-Ayland 1831ae8bb1SMark Cave-Ayland static void nubus_virtio_mmio_set_input_irq(void *opaque, int n, int level) 1931ae8bb1SMark Cave-Ayland { 2031ae8bb1SMark Cave-Ayland NubusDevice *nd = NUBUS_DEVICE(opaque); 2131ae8bb1SMark Cave-Ayland 2231ae8bb1SMark Cave-Ayland nubus_set_irq(nd, level); 2331ae8bb1SMark Cave-Ayland } 2431ae8bb1SMark Cave-Ayland 2531ae8bb1SMark Cave-Ayland static void nubus_virtio_mmio_realize(DeviceState *dev, Error **errp) 2631ae8bb1SMark Cave-Ayland { 272f28f28eSZhao Liu ERRP_GUARD(); 2831ae8bb1SMark Cave-Ayland NubusVirtioMMIODeviceClass *nvmdc = NUBUS_VIRTIO_MMIO_GET_CLASS(dev); 2931ae8bb1SMark Cave-Ayland NubusVirtioMMIO *s = NUBUS_VIRTIO_MMIO(dev); 3031ae8bb1SMark Cave-Ayland NubusDevice *nd = NUBUS_DEVICE(dev); 3131ae8bb1SMark Cave-Ayland SysBusDevice *sbd; 3231ae8bb1SMark Cave-Ayland int i, offset; 3331ae8bb1SMark Cave-Ayland 3431ae8bb1SMark Cave-Ayland nvmdc->parent_realize(dev, errp); 3531ae8bb1SMark Cave-Ayland if (*errp) { 3631ae8bb1SMark Cave-Ayland return; 3731ae8bb1SMark Cave-Ayland } 3831ae8bb1SMark Cave-Ayland 3931ae8bb1SMark Cave-Ayland /* Goldfish PIC */ 4031ae8bb1SMark Cave-Ayland sbd = SYS_BUS_DEVICE(&s->pic); 4131ae8bb1SMark Cave-Ayland if (!sysbus_realize(sbd, errp)) { 4231ae8bb1SMark Cave-Ayland return; 4331ae8bb1SMark Cave-Ayland } 4431ae8bb1SMark Cave-Ayland memory_region_add_subregion(&nd->slot_mem, NUBUS_VIRTIO_MMIO_PIC_OFFSET, 4531ae8bb1SMark Cave-Ayland sysbus_mmio_get_region(sbd, 0)); 4631ae8bb1SMark Cave-Ayland sysbus_connect_irq(sbd, 0, 4731ae8bb1SMark Cave-Ayland qdev_get_gpio_in_named(dev, "pic-input-irq", 0)); 4831ae8bb1SMark Cave-Ayland 4931ae8bb1SMark Cave-Ayland /* virtio-mmio devices */ 5031ae8bb1SMark Cave-Ayland offset = NUBUS_VIRTIO_MMIO_DEV_OFFSET; 5131ae8bb1SMark Cave-Ayland for (i = 0; i < NUBUS_VIRTIO_MMIO_NUM_DEVICES; i++) { 5231ae8bb1SMark Cave-Ayland sbd = SYS_BUS_DEVICE(&s->virtio_mmio[i]); 5331ae8bb1SMark Cave-Ayland qdev_prop_set_bit(DEVICE(sbd), "force-legacy", false); 5431ae8bb1SMark Cave-Ayland if (!sysbus_realize_and_unref(sbd, errp)) { 5531ae8bb1SMark Cave-Ayland return; 5631ae8bb1SMark Cave-Ayland } 5731ae8bb1SMark Cave-Ayland 5831ae8bb1SMark Cave-Ayland memory_region_add_subregion(&nd->slot_mem, offset, 5931ae8bb1SMark Cave-Ayland sysbus_mmio_get_region(sbd, 0)); 6031ae8bb1SMark Cave-Ayland offset += 0x200; 6131ae8bb1SMark Cave-Ayland 6231ae8bb1SMark Cave-Ayland sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(DEVICE(&s->pic), i)); 6331ae8bb1SMark Cave-Ayland } 6431ae8bb1SMark Cave-Ayland } 6531ae8bb1SMark Cave-Ayland 6631ae8bb1SMark Cave-Ayland static void nubus_virtio_mmio_init(Object *obj) 6731ae8bb1SMark Cave-Ayland { 6831ae8bb1SMark Cave-Ayland NubusVirtioMMIO *s = NUBUS_VIRTIO_MMIO(obj); 6931ae8bb1SMark Cave-Ayland int i; 7031ae8bb1SMark Cave-Ayland 7131ae8bb1SMark Cave-Ayland object_initialize_child(obj, "pic", &s->pic, TYPE_GOLDFISH_PIC); 7231ae8bb1SMark Cave-Ayland for (i = 0; i < NUBUS_VIRTIO_MMIO_NUM_DEVICES; i++) { 7331ae8bb1SMark Cave-Ayland char *name = g_strdup_printf("virtio-mmio[%d]", i); 7431ae8bb1SMark Cave-Ayland object_initialize_child(obj, name, &s->virtio_mmio[i], 7531ae8bb1SMark Cave-Ayland TYPE_VIRTIO_MMIO); 7631ae8bb1SMark Cave-Ayland g_free(name); 7731ae8bb1SMark Cave-Ayland } 7831ae8bb1SMark Cave-Ayland 7931ae8bb1SMark Cave-Ayland /* Input from goldfish PIC */ 8031ae8bb1SMark Cave-Ayland qdev_init_gpio_in_named(DEVICE(obj), nubus_virtio_mmio_set_input_irq, 8131ae8bb1SMark Cave-Ayland "pic-input-irq", 1); 8231ae8bb1SMark Cave-Ayland } 8331ae8bb1SMark Cave-Ayland 84*12d1a768SPhilippe Mathieu-Daudé static void nubus_virtio_mmio_class_init(ObjectClass *oc, const void *data) 8531ae8bb1SMark Cave-Ayland { 8631ae8bb1SMark Cave-Ayland DeviceClass *dc = DEVICE_CLASS(oc); 8731ae8bb1SMark Cave-Ayland NubusVirtioMMIODeviceClass *nvmdc = NUBUS_VIRTIO_MMIO_CLASS(oc); 8831ae8bb1SMark Cave-Ayland 8931ae8bb1SMark Cave-Ayland device_class_set_parent_realize(dc, nubus_virtio_mmio_realize, 9031ae8bb1SMark Cave-Ayland &nvmdc->parent_realize); 9131ae8bb1SMark Cave-Ayland } 9231ae8bb1SMark Cave-Ayland 9331ae8bb1SMark Cave-Ayland static const TypeInfo nubus_virtio_mmio_types[] = { 9431ae8bb1SMark Cave-Ayland { 9531ae8bb1SMark Cave-Ayland .name = TYPE_NUBUS_VIRTIO_MMIO, 9631ae8bb1SMark Cave-Ayland .parent = TYPE_NUBUS_DEVICE, 9731ae8bb1SMark Cave-Ayland .instance_init = nubus_virtio_mmio_init, 9831ae8bb1SMark Cave-Ayland .instance_size = sizeof(NubusVirtioMMIO), 9931ae8bb1SMark Cave-Ayland .class_init = nubus_virtio_mmio_class_init, 10031ae8bb1SMark Cave-Ayland .class_size = sizeof(NubusVirtioMMIODeviceClass), 10131ae8bb1SMark Cave-Ayland }, 10231ae8bb1SMark Cave-Ayland }; 10331ae8bb1SMark Cave-Ayland 10431ae8bb1SMark Cave-Ayland DEFINE_TYPES(nubus_virtio_mmio_types) 105