4 * Copyright (c) 2013-2018 Laurent Vivier <laurent@vivier.eu>
6 * This work is licensed under the terms of the GNU GPL, version 2 or later.
7 * See the COPYING file in the top-level directory.
13 * Nubus Specification (TI)
14 * http://www.bitsavers.org/pdf/ti/nubus/2242825-0001_NuBus_Spec1983.pdf
16 * Designing Cards and Drivers for the Macintosh Family (Apple)
19 #include "qemu/osdep.h"
20 #include "hw/nubus/nubus.h"
21 #include "qapi/error.h"
25 static NubusBus
*nubus_find(void)
27 /* Returns NULL unless there is exactly one nubus device */
28 return NUBUS_BUS(object_resolve_path_type("", TYPE_NUBUS_BUS
, NULL
));
31 static MemTxResult
nubus_slot_write(void *opaque
, hwaddr addr
, uint64_t val
,
32 unsigned size
, MemTxAttrs attrs
)
34 trace_nubus_slot_write(addr
, val
, size
);
35 return MEMTX_DECODE_ERROR
;
38 static MemTxResult
nubus_slot_read(void *opaque
, hwaddr addr
, uint64_t *data
,
39 unsigned size
, MemTxAttrs attrs
)
41 trace_nubus_slot_read(addr
, size
);
42 return MEMTX_DECODE_ERROR
;
45 static const MemoryRegionOps nubus_slot_ops
= {
46 .read_with_attrs
= nubus_slot_read
,
47 .write_with_attrs
= nubus_slot_write
,
48 .endianness
= DEVICE_BIG_ENDIAN
,
55 static MemTxResult
nubus_super_slot_write(void *opaque
, hwaddr addr
,
56 uint64_t val
, unsigned size
,
59 trace_nubus_super_slot_write(addr
, val
, size
);
60 return MEMTX_DECODE_ERROR
;
63 static MemTxResult
nubus_super_slot_read(void *opaque
, hwaddr addr
,
64 uint64_t *data
, unsigned size
,
67 trace_nubus_super_slot_read(addr
, size
);
68 return MEMTX_DECODE_ERROR
;
71 static const MemoryRegionOps nubus_super_slot_ops
= {
72 .read_with_attrs
= nubus_super_slot_read
,
73 .write_with_attrs
= nubus_super_slot_write
,
74 .endianness
= DEVICE_BIG_ENDIAN
,
81 static void nubus_unrealize(BusState
*bus
)
83 NubusBus
*nubus
= NUBUS_BUS(bus
);
85 address_space_destroy(&nubus
->nubus_as
);
88 static void nubus_realize(BusState
*bus
, Error
**errp
)
90 NubusBus
*nubus
= NUBUS_BUS(bus
);
93 error_setg(errp
, "at most one %s device is permitted", TYPE_NUBUS_BUS
);
97 address_space_init(&nubus
->nubus_as
, &nubus
->nubus_mr
, "nubus");
100 static void nubus_init(Object
*obj
)
102 NubusBus
*nubus
= NUBUS_BUS(obj
);
104 memory_region_init(&nubus
->nubus_mr
, obj
, "nubus", 0x100000000);
106 memory_region_init_io(&nubus
->super_slot_io
, obj
, &nubus_super_slot_ops
,
107 nubus
, "nubus-super-slots",
108 (NUBUS_SUPER_SLOT_NB
+ 1) * NUBUS_SUPER_SLOT_SIZE
);
109 memory_region_add_subregion(&nubus
->nubus_mr
, 0x0, &nubus
->super_slot_io
);
111 memory_region_init_io(&nubus
->slot_io
, obj
, &nubus_slot_ops
,
112 nubus
, "nubus-slots",
113 NUBUS_SLOT_NB
* NUBUS_SLOT_SIZE
);
114 memory_region_add_subregion(&nubus
->nubus_mr
,
115 (NUBUS_SUPER_SLOT_NB
+ 1) *
116 NUBUS_SUPER_SLOT_SIZE
, &nubus
->slot_io
);
118 nubus
->slot_available_mask
= MAKE_64BIT_MASK(NUBUS_FIRST_SLOT
,
122 static char *nubus_get_dev_path(DeviceState
*dev
)
124 NubusDevice
*nd
= NUBUS_DEVICE(dev
);
125 BusState
*bus
= qdev_get_parent_bus(dev
);
126 char *p
= qdev_get_dev_path(bus
->parent
);
129 char *ret
= g_strdup_printf("%s/%s/%02x", p
, bus
->name
, nd
->slot
);
133 return g_strdup_printf("%s/%02x", bus
->name
, nd
->slot
);
137 static bool nubus_check_address(BusState
*bus
, DeviceState
*dev
, Error
**errp
)
139 NubusDevice
*nd
= NUBUS_DEVICE(dev
);
140 NubusBus
*nubus
= NUBUS_BUS(bus
);
142 if (nd
->slot
== -1) {
143 /* No slot specified, find first available free slot */
144 int s
= ctz32(nubus
->slot_available_mask
);
148 error_setg(errp
, "Cannot register nubus card, no free slot "
153 /* Slot specified, make sure the slot is available */
154 if (!(nubus
->slot_available_mask
& BIT(nd
->slot
))) {
155 error_setg(errp
, "Cannot register nubus card, slot %d is "
156 "unavailable or already occupied", nd
->slot
);
161 nubus
->slot_available_mask
&= ~BIT(nd
->slot
);
165 static void nubus_class_init(ObjectClass
*oc
, void *data
)
167 BusClass
*bc
= BUS_CLASS(oc
);
169 bc
->realize
= nubus_realize
;
170 bc
->unrealize
= nubus_unrealize
;
171 bc
->check_address
= nubus_check_address
;
172 bc
->get_dev_path
= nubus_get_dev_path
;
175 static const TypeInfo nubus_bus_info
= {
176 .name
= TYPE_NUBUS_BUS
,
178 .instance_size
= sizeof(NubusBus
),
179 .instance_init
= nubus_init
,
180 .class_init
= nubus_class_init
,
183 static void nubus_register_types(void)
185 type_register_static(&nubus_bus_info
);
188 type_init(nubus_register_types
)