1fa2ba3b8SLaurent Vivier /* 2fa2ba3b8SLaurent Vivier * QEMU Macintosh Nubus 3fa2ba3b8SLaurent Vivier * 4fa2ba3b8SLaurent Vivier * Copyright (c) 2013-2018 Laurent Vivier <laurent@vivier.eu> 5fa2ba3b8SLaurent Vivier * 6fa2ba3b8SLaurent Vivier * This work is licensed under the terms of the GNU GPL, version 2 or later. 7fa2ba3b8SLaurent Vivier * See the COPYING file in the top-level directory. 8fa2ba3b8SLaurent Vivier * 9fa2ba3b8SLaurent Vivier */ 10fa2ba3b8SLaurent Vivier 11*5d1fa7e4SMark Cave-Ayland /* 12*5d1fa7e4SMark Cave-Ayland * References: 13*5d1fa7e4SMark Cave-Ayland * Nubus Specification (TI) 14*5d1fa7e4SMark Cave-Ayland * http://www.bitsavers.org/pdf/ti/nubus/2242825-0001_NuBus_Spec1983.pdf 15*5d1fa7e4SMark Cave-Ayland * 16*5d1fa7e4SMark Cave-Ayland * Designing Cards and Drivers for the Macintosh Family (Apple) 17*5d1fa7e4SMark Cave-Ayland */ 18*5d1fa7e4SMark Cave-Ayland 19fa2ba3b8SLaurent Vivier #include "qemu/osdep.h" 20fa2ba3b8SLaurent Vivier #include "hw/nubus/nubus.h" 21fa2ba3b8SLaurent Vivier #include "qapi/error.h" 22fa2ba3b8SLaurent Vivier 23fa2ba3b8SLaurent Vivier 24fa2ba3b8SLaurent Vivier static NubusBus *nubus_find(void) 25fa2ba3b8SLaurent Vivier { 26fa2ba3b8SLaurent Vivier /* Returns NULL unless there is exactly one nubus device */ 27fa2ba3b8SLaurent Vivier return NUBUS_BUS(object_resolve_path_type("", TYPE_NUBUS_BUS, NULL)); 28fa2ba3b8SLaurent Vivier } 29fa2ba3b8SLaurent Vivier 30fa2ba3b8SLaurent Vivier static void nubus_slot_write(void *opaque, hwaddr addr, uint64_t val, 31fa2ba3b8SLaurent Vivier unsigned int size) 32fa2ba3b8SLaurent Vivier { 33fa2ba3b8SLaurent Vivier /* read only */ 34fa2ba3b8SLaurent Vivier } 35fa2ba3b8SLaurent Vivier 36fa2ba3b8SLaurent Vivier 37fa2ba3b8SLaurent Vivier static uint64_t nubus_slot_read(void *opaque, hwaddr addr, 38fa2ba3b8SLaurent Vivier unsigned int size) 39fa2ba3b8SLaurent Vivier { 40fa2ba3b8SLaurent Vivier return 0; 41fa2ba3b8SLaurent Vivier } 42fa2ba3b8SLaurent Vivier 43fa2ba3b8SLaurent Vivier static const MemoryRegionOps nubus_slot_ops = { 44fa2ba3b8SLaurent Vivier .read = nubus_slot_read, 45fa2ba3b8SLaurent Vivier .write = nubus_slot_write, 46fa2ba3b8SLaurent Vivier .endianness = DEVICE_BIG_ENDIAN, 47fa2ba3b8SLaurent Vivier .valid = { 48fa2ba3b8SLaurent Vivier .min_access_size = 1, 49fa2ba3b8SLaurent Vivier .max_access_size = 1, 50fa2ba3b8SLaurent Vivier }, 51fa2ba3b8SLaurent Vivier }; 52fa2ba3b8SLaurent Vivier 53fa2ba3b8SLaurent Vivier static void nubus_super_slot_write(void *opaque, hwaddr addr, uint64_t val, 54fa2ba3b8SLaurent Vivier unsigned int size) 55fa2ba3b8SLaurent Vivier { 56fa2ba3b8SLaurent Vivier /* read only */ 57fa2ba3b8SLaurent Vivier } 58fa2ba3b8SLaurent Vivier 59fa2ba3b8SLaurent Vivier static uint64_t nubus_super_slot_read(void *opaque, hwaddr addr, 60fa2ba3b8SLaurent Vivier unsigned int size) 61fa2ba3b8SLaurent Vivier { 62fa2ba3b8SLaurent Vivier return 0; 63fa2ba3b8SLaurent Vivier } 64fa2ba3b8SLaurent Vivier 65fa2ba3b8SLaurent Vivier static const MemoryRegionOps nubus_super_slot_ops = { 66fa2ba3b8SLaurent Vivier .read = nubus_super_slot_read, 67fa2ba3b8SLaurent Vivier .write = nubus_super_slot_write, 68fa2ba3b8SLaurent Vivier .endianness = DEVICE_BIG_ENDIAN, 69fa2ba3b8SLaurent Vivier .valid = { 70fa2ba3b8SLaurent Vivier .min_access_size = 1, 71fa2ba3b8SLaurent Vivier .max_access_size = 1, 72fa2ba3b8SLaurent Vivier }, 73fa2ba3b8SLaurent Vivier }; 74fa2ba3b8SLaurent Vivier 75fa2ba3b8SLaurent Vivier static void nubus_realize(BusState *bus, Error **errp) 76fa2ba3b8SLaurent Vivier { 77fa2ba3b8SLaurent Vivier if (!nubus_find()) { 78fa2ba3b8SLaurent Vivier error_setg(errp, "at most one %s device is permitted", TYPE_NUBUS_BUS); 79fa2ba3b8SLaurent Vivier return; 80fa2ba3b8SLaurent Vivier } 81fa2ba3b8SLaurent Vivier } 82fa2ba3b8SLaurent Vivier 83fa2ba3b8SLaurent Vivier static void nubus_init(Object *obj) 84fa2ba3b8SLaurent Vivier { 85fa2ba3b8SLaurent Vivier NubusBus *nubus = NUBUS_BUS(obj); 86fa2ba3b8SLaurent Vivier 87fa2ba3b8SLaurent Vivier memory_region_init_io(&nubus->super_slot_io, obj, &nubus_super_slot_ops, 88fa2ba3b8SLaurent Vivier nubus, "nubus-super-slots", 89fa2ba3b8SLaurent Vivier NUBUS_SUPER_SLOT_NB * NUBUS_SUPER_SLOT_SIZE); 90fa2ba3b8SLaurent Vivier 91fa2ba3b8SLaurent Vivier memory_region_init_io(&nubus->slot_io, obj, &nubus_slot_ops, 92fa2ba3b8SLaurent Vivier nubus, "nubus-slots", 93fa2ba3b8SLaurent Vivier NUBUS_SLOT_NB * NUBUS_SLOT_SIZE); 94fa2ba3b8SLaurent Vivier 95fa2ba3b8SLaurent Vivier nubus->current_slot = NUBUS_FIRST_SLOT; 96fa2ba3b8SLaurent Vivier } 97fa2ba3b8SLaurent Vivier 98fa2ba3b8SLaurent Vivier static void nubus_class_init(ObjectClass *oc, void *data) 99fa2ba3b8SLaurent Vivier { 100fa2ba3b8SLaurent Vivier BusClass *bc = BUS_CLASS(oc); 101fa2ba3b8SLaurent Vivier 102fa2ba3b8SLaurent Vivier bc->realize = nubus_realize; 103fa2ba3b8SLaurent Vivier } 104fa2ba3b8SLaurent Vivier 105fa2ba3b8SLaurent Vivier static const TypeInfo nubus_bus_info = { 106fa2ba3b8SLaurent Vivier .name = TYPE_NUBUS_BUS, 107fa2ba3b8SLaurent Vivier .parent = TYPE_BUS, 108fa2ba3b8SLaurent Vivier .instance_size = sizeof(NubusBus), 109fa2ba3b8SLaurent Vivier .instance_init = nubus_init, 110fa2ba3b8SLaurent Vivier .class_init = nubus_class_init, 111fa2ba3b8SLaurent Vivier }; 112fa2ba3b8SLaurent Vivier 113fa2ba3b8SLaurent Vivier static void nubus_register_types(void) 114fa2ba3b8SLaurent Vivier { 115fa2ba3b8SLaurent Vivier type_register_static(&nubus_bus_info); 116fa2ba3b8SLaurent Vivier } 117fa2ba3b8SLaurent Vivier 118fa2ba3b8SLaurent Vivier type_init(nubus_register_types) 119