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