aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/display/macfb.c6
-rw-r--r--hw/m68k/q800.c26
-rw-r--r--hw/nubus/mac-nubus-bridge.c34
-rw-r--r--hw/nubus/nubus-bridge.c23
-rw-r--r--hw/nubus/nubus-bus.c120
-rw-r--r--hw/nubus/nubus-device.c227
-rw-r--r--hw/nubus/trace-events7
-rw-r--r--hw/nubus/trace.h1
-rw-r--r--include/hw/nubus/mac-nubus-bridge.h13
-rw-r--r--include/hw/nubus/nubus.h49
-rw-r--r--meson.build1
11 files changed, 278 insertions, 229 deletions
diff --git a/hw/display/macfb.c b/hw/display/macfb.c
index d8183b9..76808b6 100644
--- a/hw/display/macfb.c
+++ b/hw/display/macfb.c
@@ -383,10 +383,6 @@ static void macfb_sysbus_realize(DeviceState *dev, Error **errp)
sysbus_init_mmio(SYS_BUS_DEVICE(s), &ms->mem_vram);
}
-const uint8_t macfb_rom[] = {
- 255, 0, 0, 0,
-};
-
static void macfb_nubus_realize(DeviceState *dev, Error **errp)
{
NubusDevice *nd = NUBUS_DEVICE(dev);
@@ -399,8 +395,6 @@ static void macfb_nubus_realize(DeviceState *dev, Error **errp)
macfb_common_realize(dev, ms, errp);
memory_region_add_subregion(&nd->slot_mem, DAFB_BASE, &ms->mem_ctrl);
memory_region_add_subregion(&nd->slot_mem, VIDEO_BASE, &ms->mem_vram);
-
- nubus_register_rom(nd, macfb_rom, sizeof(macfb_rom), 1, 9, 0xf);
}
static void macfb_sysbus_reset(DeviceState *d)
diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c
index 5ba87f7..09b3366 100644
--- a/hw/m68k/q800.c
+++ b/hw/m68k/q800.c
@@ -67,9 +67,6 @@
#define ASC_BASE (IO_BASE + 0x14000)
#define SWIM_BASE (IO_BASE + 0x1E000)
-#define NUBUS_SUPER_SLOT_BASE 0x60000000
-#define NUBUS_SLOT_BASE 0xf0000000
-
#define SONIC_PROM_SIZE 0x1000
/*
@@ -82,6 +79,13 @@
#define MAC_CLOCK 3686418
/*
+ * Slot 0x9 is reserved for use by the in-built framebuffer whilst only
+ * slots 0xc, 0xd and 0xe physically exist on the Quadra 800
+ */
+#define Q800_NUBUS_SLOTS_AVAILABLE (BIT(0x9) | BIT(0xc) | BIT(0xd) | \
+ BIT(0xe))
+
+/*
* The GLUE (General Logic Unit) is an Apple custom integrated circuit chip
* that performs a variety of functions (RAM management, clock generation, ...).
* The GLUE chip receives interrupt requests from various devices,
@@ -395,11 +399,21 @@ static void q800_init(MachineState *machine)
/* NuBus */
dev = qdev_new(TYPE_MAC_NUBUS_BRIDGE);
+ qdev_prop_set_uint32(dev, "slot-available-mask",
+ Q800_NUBUS_SLOTS_AVAILABLE);
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
- sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, NUBUS_SUPER_SLOT_BASE);
- sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, NUBUS_SLOT_BASE);
+ sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0,
+ MAC_NUBUS_FIRST_SLOT * NUBUS_SUPER_SLOT_SIZE);
+ sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, NUBUS_SLOT_BASE +
+ MAC_NUBUS_FIRST_SLOT * NUBUS_SLOT_SIZE);
+
+ for (i = 0; i < VIA2_NUBUS_IRQ_NB; i++) {
+ qdev_connect_gpio_out(dev, 9 + i,
+ qdev_get_gpio_in_named(via2_dev, "nubus-irq",
+ VIA2_NUBUS_IRQ_9 + i));
+ }
- nubus = MAC_NUBUS_BRIDGE(dev)->bus;
+ nubus = &NUBUS_BRIDGE(dev)->bus;
/* framebuffer in nubus slot #9 */
diff --git a/hw/nubus/mac-nubus-bridge.c b/hw/nubus/mac-nubus-bridge.c
index 7c32930..a0da5a8 100644
--- a/hw/nubus/mac-nubus-bridge.c
+++ b/hw/nubus/mac-nubus-bridge.c
@@ -1,5 +1,7 @@
/*
- * Copyright (c) 2013-2018 Laurent Vivier <laurent@vivier.eu>
+ * QEMU Macintosh Nubus
+ *
+ * Copyright (c) 2013-2018 Laurent Vivier <laurent@vivier.eu>
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
@@ -13,13 +15,29 @@
static void mac_nubus_bridge_init(Object *obj)
{
- MacNubusState *s = MAC_NUBUS_BRIDGE(obj);
+ MacNubusBridge *s = MAC_NUBUS_BRIDGE(obj);
+ NubusBridge *nb = NUBUS_BRIDGE(obj);
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
-
- s->bus = NUBUS_BUS(qbus_create(TYPE_NUBUS_BUS, DEVICE(s), NULL));
-
- sysbus_init_mmio(sbd, &s->bus->super_slot_io);
- sysbus_init_mmio(sbd, &s->bus->slot_io);
+ NubusBus *bus = &nb->bus;
+
+ /* Macintosh only has slots 0x9 to 0xe available */
+ bus->slot_available_mask = MAKE_64BIT_MASK(MAC_NUBUS_FIRST_SLOT,
+ MAC_NUBUS_SLOT_NB);
+
+ /* Aliases for slots 0x9 to 0xe */
+ memory_region_init_alias(&s->super_slot_alias, obj, "super-slot-alias",
+ &bus->nubus_mr,
+ MAC_NUBUS_FIRST_SLOT * NUBUS_SUPER_SLOT_SIZE,
+ MAC_NUBUS_SLOT_NB * NUBUS_SUPER_SLOT_SIZE);
+
+ memory_region_init_alias(&s->slot_alias, obj, "slot-alias",
+ &bus->nubus_mr,
+ NUBUS_SLOT_BASE +
+ MAC_NUBUS_FIRST_SLOT * NUBUS_SLOT_SIZE,
+ MAC_NUBUS_SLOT_NB * NUBUS_SLOT_SIZE);
+
+ sysbus_init_mmio(sbd, &s->super_slot_alias);
+ sysbus_init_mmio(sbd, &s->slot_alias);
}
static void mac_nubus_bridge_class_init(ObjectClass *klass, void *data)
@@ -33,7 +51,7 @@ static const TypeInfo mac_nubus_bridge_info = {
.name = TYPE_MAC_NUBUS_BRIDGE,
.parent = TYPE_NUBUS_BRIDGE,
.instance_init = mac_nubus_bridge_init,
- .instance_size = sizeof(MacNubusState),
+ .instance_size = sizeof(MacNubusBridge),
.class_init = mac_nubus_bridge_class_init,
};
diff --git a/hw/nubus/nubus-bridge.c b/hw/nubus/nubus-bridge.c
index cd8c6a9..c517a8a 100644
--- a/hw/nubus/nubus-bridge.c
+++ b/hw/nubus/nubus-bridge.c
@@ -1,5 +1,5 @@
/*
- * QEMU Macintosh Nubus
+ * QEMU Nubus
*
* Copyright (c) 2013-2018 Laurent Vivier <laurent@vivier.eu>
*
@@ -12,17 +12,36 @@
#include "hw/sysbus.h"
#include "hw/nubus/nubus.h"
+
+static void nubus_bridge_init(Object *obj)
+{
+ NubusBridge *s = NUBUS_BRIDGE(obj);
+ NubusBus *bus = &s->bus;
+
+ qbus_create_inplace(bus, sizeof(s->bus), TYPE_NUBUS_BUS, DEVICE(s), NULL);
+
+ qdev_init_gpio_out(DEVICE(s), bus->irqs, NUBUS_IRQS);
+}
+
+static Property nubus_bridge_properties[] = {
+ DEFINE_PROP_UINT16("slot-available-mask", NubusBridge,
+ bus.slot_available_mask, 0xffff),
+ DEFINE_PROP_END_OF_LIST()
+};
+
static void nubus_bridge_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->fw_name = "nubus";
+ device_class_set_props(dc, nubus_bridge_properties);
}
static const TypeInfo nubus_bridge_info = {
.name = TYPE_NUBUS_BRIDGE,
.parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(SysBusDevice),
+ .instance_init = nubus_bridge_init,
+ .instance_size = sizeof(NubusBridge),
.class_init = nubus_bridge_class_init,
};
diff --git a/hw/nubus/nubus-bus.c b/hw/nubus/nubus-bus.c
index 5c13452..07c279b 100644
--- a/hw/nubus/nubus-bus.c
+++ b/hw/nubus/nubus-bus.c
@@ -8,9 +8,18 @@
*
*/
+/*
+ * References:
+ * Nubus Specification (TI)
+ * http://www.bitsavers.org/pdf/ti/nubus/2242825-0001_NuBus_Spec1983.pdf
+ *
+ * Designing Cards and Drivers for the Macintosh Family (Apple)
+ */
+
#include "qemu/osdep.h"
#include "hw/nubus/nubus.h"
#include "qapi/error.h"
+#include "trace.h"
static NubusBus *nubus_find(void)
@@ -19,72 +28,138 @@ static NubusBus *nubus_find(void)
return NUBUS_BUS(object_resolve_path_type("", TYPE_NUBUS_BUS, NULL));
}
-static void nubus_slot_write(void *opaque, hwaddr addr, uint64_t val,
- unsigned int size)
+static MemTxResult nubus_slot_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned size, MemTxAttrs attrs)
{
- /* read only */
+ trace_nubus_slot_write(addr, val, size);
+ return MEMTX_DECODE_ERROR;
}
-
-static uint64_t nubus_slot_read(void *opaque, hwaddr addr,
- unsigned int size)
+static MemTxResult nubus_slot_read(void *opaque, hwaddr addr, uint64_t *data,
+ unsigned size, MemTxAttrs attrs)
{
- return 0;
+ trace_nubus_slot_read(addr, size);
+ return MEMTX_DECODE_ERROR;
}
static const MemoryRegionOps nubus_slot_ops = {
- .read = nubus_slot_read,
- .write = nubus_slot_write,
+ .read_with_attrs = nubus_slot_read,
+ .write_with_attrs = nubus_slot_write,
.endianness = DEVICE_BIG_ENDIAN,
.valid = {
.min_access_size = 1,
- .max_access_size = 1,
+ .max_access_size = 4,
},
};
-static void nubus_super_slot_write(void *opaque, hwaddr addr, uint64_t val,
- unsigned int size)
+static MemTxResult nubus_super_slot_write(void *opaque, hwaddr addr,
+ uint64_t val, unsigned size,
+ MemTxAttrs attrs)
{
- /* read only */
+ trace_nubus_super_slot_write(addr, val, size);
+ return MEMTX_DECODE_ERROR;
}
-static uint64_t nubus_super_slot_read(void *opaque, hwaddr addr,
- unsigned int size)
+static MemTxResult nubus_super_slot_read(void *opaque, hwaddr addr,
+ uint64_t *data, unsigned size,
+ MemTxAttrs attrs)
{
- return 0;
+ trace_nubus_super_slot_read(addr, size);
+ return MEMTX_DECODE_ERROR;
}
static const MemoryRegionOps nubus_super_slot_ops = {
- .read = nubus_super_slot_read,
- .write = nubus_super_slot_write,
+ .read_with_attrs = nubus_super_slot_read,
+ .write_with_attrs = nubus_super_slot_write,
.endianness = DEVICE_BIG_ENDIAN,
.valid = {
.min_access_size = 1,
- .max_access_size = 1,
+ .max_access_size = 4,
},
};
+static void nubus_unrealize(BusState *bus)
+{
+ NubusBus *nubus = NUBUS_BUS(bus);
+
+ address_space_destroy(&nubus->nubus_as);
+}
+
static void nubus_realize(BusState *bus, Error **errp)
{
+ NubusBus *nubus = NUBUS_BUS(bus);
+
if (!nubus_find()) {
error_setg(errp, "at most one %s device is permitted", TYPE_NUBUS_BUS);
return;
}
+
+ address_space_init(&nubus->nubus_as, &nubus->nubus_mr, "nubus");
}
static void nubus_init(Object *obj)
{
NubusBus *nubus = NUBUS_BUS(obj);
+ memory_region_init(&nubus->nubus_mr, obj, "nubus", 0x100000000);
+
memory_region_init_io(&nubus->super_slot_io, obj, &nubus_super_slot_ops,
nubus, "nubus-super-slots",
- NUBUS_SUPER_SLOT_NB * NUBUS_SUPER_SLOT_SIZE);
+ (NUBUS_SUPER_SLOT_NB + 1) * NUBUS_SUPER_SLOT_SIZE);
+ memory_region_add_subregion(&nubus->nubus_mr, 0x0, &nubus->super_slot_io);
memory_region_init_io(&nubus->slot_io, obj, &nubus_slot_ops,
nubus, "nubus-slots",
NUBUS_SLOT_NB * NUBUS_SLOT_SIZE);
+ memory_region_add_subregion(&nubus->nubus_mr,
+ (NUBUS_SUPER_SLOT_NB + 1) *
+ NUBUS_SUPER_SLOT_SIZE, &nubus->slot_io);
+
+ nubus->slot_available_mask = MAKE_64BIT_MASK(NUBUS_FIRST_SLOT,
+ NUBUS_SLOT_NB);
+}
+
+static char *nubus_get_dev_path(DeviceState *dev)
+{
+ NubusDevice *nd = NUBUS_DEVICE(dev);
+ BusState *bus = qdev_get_parent_bus(dev);
+ char *p = qdev_get_dev_path(bus->parent);
+
+ if (p) {
+ char *ret = g_strdup_printf("%s/%s/%02x", p, bus->name, nd->slot);
+ g_free(p);
+ return ret;
+ } else {
+ return g_strdup_printf("%s/%02x", bus->name, nd->slot);
+ }
+}
+
+static bool nubus_check_address(BusState *bus, DeviceState *dev, Error **errp)
+{
+ NubusDevice *nd = NUBUS_DEVICE(dev);
+ NubusBus *nubus = NUBUS_BUS(bus);
+
+ if (nd->slot == -1) {
+ /* No slot specified, find first available free slot */
+ int s = ctz32(nubus->slot_available_mask);
+ if (s != 32) {
+ nd->slot = s;
+ } else {
+ error_setg(errp, "Cannot register nubus card, no free slot "
+ "available");
+ return false;
+ }
+ } else {
+ /* Slot specified, make sure the slot is available */
+ if (!(nubus->slot_available_mask & BIT(nd->slot))) {
+ error_setg(errp, "Cannot register nubus card, slot %d is "
+ "unavailable or already occupied", nd->slot);
+ return false;
+ }
+ }
- nubus->current_slot = NUBUS_FIRST_SLOT;
+ nubus->slot_available_mask &= ~BIT(nd->slot);
+ return true;
}
static void nubus_class_init(ObjectClass *oc, void *data)
@@ -92,6 +167,9 @@ static void nubus_class_init(ObjectClass *oc, void *data)
BusClass *bc = BUS_CLASS(oc);
bc->realize = nubus_realize;
+ bc->unrealize = nubus_unrealize;
+ bc->check_address = nubus_check_address;
+ bc->get_dev_path = nubus_get_dev_path;
}
static const TypeInfo nubus_bus_info = {
diff --git a/hw/nubus/nubus-device.c b/hw/nubus/nubus-device.c
index ffe78a8..0f1852f 100644
--- a/hw/nubus/nubus-device.c
+++ b/hw/nubus/nubus-device.c
@@ -9,194 +9,99 @@
*/
#include "qemu/osdep.h"
+#include "qemu/datadir.h"
+#include "hw/irq.h"
+#include "hw/loader.h"
#include "hw/nubus/nubus.h"
#include "qapi/error.h"
+#include "qemu/error-report.h"
-/* The Format Block Structure */
-
-#define FBLOCK_DIRECTORY_OFFSET 0
-#define FBLOCK_LENGTH 4
-#define FBLOCK_CRC 8
-#define FBLOCK_REVISION_LEVEL 12
-#define FBLOCK_FORMAT 13
-#define FBLOCK_TEST_PATTERN 14
-#define FBLOCK_RESERVED 18
-#define FBLOCK_BYTE_LANES 19
-
-#define FBLOCK_SIZE 20
-#define FBLOCK_PATTERN_VAL 0x5a932bc7
-
-static uint64_t nubus_fblock_read(void *opaque, hwaddr addr, unsigned int size)
-{
- NubusDevice *dev = opaque;
- uint64_t val;
-
-#define BYTE(v, b) (((v) >> (24 - 8 * (b))) & 0xff)
- switch (addr) {
- case FBLOCK_BYTE_LANES:
- val = dev->byte_lanes;
- val |= (val ^ 0xf) << 4;
- break;
- case FBLOCK_RESERVED:
- val = 0x00;
- break;
- case FBLOCK_TEST_PATTERN...FBLOCK_TEST_PATTERN + 3:
- val = BYTE(FBLOCK_PATTERN_VAL, addr - FBLOCK_TEST_PATTERN);
- break;
- case FBLOCK_FORMAT:
- val = dev->rom_format;
- break;
- case FBLOCK_REVISION_LEVEL:
- val = dev->rom_rev;
- break;
- case FBLOCK_CRC...FBLOCK_CRC + 3:
- val = BYTE(dev->rom_crc, addr - FBLOCK_CRC);
- break;
- case FBLOCK_LENGTH...FBLOCK_LENGTH + 3:
- val = BYTE(dev->rom_length, addr - FBLOCK_LENGTH);
- break;
- case FBLOCK_DIRECTORY_OFFSET...FBLOCK_DIRECTORY_OFFSET + 3:
- val = BYTE(dev->directory_offset, addr - FBLOCK_DIRECTORY_OFFSET);
- break;
- default:
- val = 0;
- break;
- }
- return val;
-}
-
-static void nubus_fblock_write(void *opaque, hwaddr addr, uint64_t val,
- unsigned int size)
-{
- /* read only */
-}
-
-static const MemoryRegionOps nubus_format_block_ops = {
- .read = nubus_fblock_read,
- .write = nubus_fblock_write,
- .endianness = DEVICE_BIG_ENDIAN,
- .valid = {
- .min_access_size = 1,
- .max_access_size = 1,
- }
-};
-
-static void nubus_register_format_block(NubusDevice *dev)
-{
- char *fblock_name;
-
- fblock_name = g_strdup_printf("nubus-slot-%d-format-block",
- dev->slot_nb);
-
- hwaddr fblock_offset = memory_region_size(&dev->slot_mem) - FBLOCK_SIZE;
- memory_region_init_io(&dev->fblock_io, NULL, &nubus_format_block_ops,
- dev, fblock_name, FBLOCK_SIZE);
- memory_region_add_subregion(&dev->slot_mem, fblock_offset,
- &dev->fblock_io);
-
- g_free(fblock_name);
-}
-
-static void mac_nubus_rom_write(void *opaque, hwaddr addr, uint64_t val,
- unsigned int size)
-{
- /* read only */
-}
-
-static uint64_t mac_nubus_rom_read(void *opaque, hwaddr addr,
- unsigned int size)
+void nubus_set_irq(NubusDevice *nd, int level)
{
- NubusDevice *dev = opaque;
+ NubusBus *nubus = NUBUS_BUS(qdev_get_parent_bus(DEVICE(nd)));
- return dev->rom[addr];
-}
-
-static const MemoryRegionOps mac_nubus_rom_ops = {
- .read = mac_nubus_rom_read,
- .write = mac_nubus_rom_write,
- .endianness = DEVICE_BIG_ENDIAN,
- .valid = {
- .min_access_size = 1,
- .max_access_size = 1,
- },
-};
-
-
-void nubus_register_rom(NubusDevice *dev, const uint8_t *rom, uint32_t size,
- int revision, int format, uint8_t byte_lanes)
-{
- hwaddr rom_offset;
- char *rom_name;
-
- /* FIXME : really compute CRC */
- dev->rom_length = 0;
- dev->rom_crc = 0;
-
- dev->rom_rev = revision;
- dev->rom_format = format;
-
- dev->byte_lanes = byte_lanes;
- dev->directory_offset = -size;
-
- /* ROM */
-
- dev->rom = rom;
- rom_name = g_strdup_printf("nubus-slot-%d-rom", dev->slot_nb);
- memory_region_init_io(&dev->rom_io, NULL, &mac_nubus_rom_ops,
- dev, rom_name, size);
- memory_region_set_readonly(&dev->rom_io, true);
-
- rom_offset = memory_region_size(&dev->slot_mem) - FBLOCK_SIZE +
- dev->directory_offset;
- memory_region_add_subregion(&dev->slot_mem, rom_offset, &dev->rom_io);
-
- g_free(rom_name);
+ qemu_set_irq(nubus->irqs[nd->slot], level);
}
static void nubus_device_realize(DeviceState *dev, Error **errp)
{
NubusBus *nubus = NUBUS_BUS(qdev_get_parent_bus(dev));
NubusDevice *nd = NUBUS_DEVICE(dev);
- char *name;
+ char *name, *path;
hwaddr slot_offset;
+ int64_t size;
+ int ret;
- if (nubus->current_slot < NUBUS_FIRST_SLOT ||
- nubus->current_slot > NUBUS_LAST_SLOT) {
- error_setg(errp, "Cannot register nubus card, not enough slots");
- return;
- }
+ /* Super */
+ slot_offset = nd->slot * NUBUS_SUPER_SLOT_SIZE;
- nd->slot_nb = nubus->current_slot++;
- name = g_strdup_printf("nubus-slot-%d", nd->slot_nb);
+ name = g_strdup_printf("nubus-super-slot-%x", nd->slot);
+ memory_region_init(&nd->super_slot_mem, OBJECT(dev), name,
+ NUBUS_SUPER_SLOT_SIZE);
+ memory_region_add_subregion(&nubus->super_slot_io, slot_offset,
+ &nd->super_slot_mem);
+ g_free(name);
- if (nd->slot_nb < NUBUS_FIRST_SLOT) {
- /* Super */
- slot_offset = (nd->slot_nb - 6) * NUBUS_SUPER_SLOT_SIZE;
+ /* Normal */
+ slot_offset = nd->slot * NUBUS_SLOT_SIZE;
- memory_region_init(&nd->slot_mem, OBJECT(dev), name,
- NUBUS_SUPER_SLOT_SIZE);
- memory_region_add_subregion(&nubus->super_slot_io, slot_offset,
- &nd->slot_mem);
- } else {
- /* Normal */
- slot_offset = nd->slot_nb * NUBUS_SLOT_SIZE;
+ name = g_strdup_printf("nubus-slot-%x", nd->slot);
+ memory_region_init(&nd->slot_mem, OBJECT(dev), name, NUBUS_SLOT_SIZE);
+ memory_region_add_subregion(&nubus->slot_io, slot_offset,
+ &nd->slot_mem);
+ g_free(name);
- memory_region_init(&nd->slot_mem, OBJECT(dev), name, NUBUS_SLOT_SIZE);
- memory_region_add_subregion(&nubus->slot_io, slot_offset,
- &nd->slot_mem);
+ /* Declaration ROM */
+ if (nd->romfile != NULL) {
+ path = qemu_find_file(QEMU_FILE_TYPE_BIOS, nd->romfile);
+ if (path == NULL) {
+ path = g_strdup(nd->romfile);
+ }
+
+ size = get_image_size(path);
+ if (size < 0) {
+ error_setg(errp, "failed to find romfile \"%s\"", nd->romfile);
+ g_free(path);
+ return;
+ } else if (size == 0) {
+ error_setg(errp, "romfile \"%s\" is empty", nd->romfile);
+ g_free(path);
+ return;
+ } else if (size > NUBUS_DECL_ROM_MAX_SIZE) {
+ error_setg(errp, "romfile \"%s\" too large (maximum size 128K)",
+ nd->romfile);
+ g_free(path);
+ return;
+ }
+
+ name = g_strdup_printf("nubus-slot-%x-declaration-rom", nd->slot);
+ memory_region_init_rom(&nd->decl_rom, OBJECT(dev), name, size,
+ &error_abort);
+ ret = load_image_mr(path, &nd->decl_rom);
+ g_free(path);
+ if (ret < 0) {
+ error_setg(errp, "could not load romfile \"%s\"", nd->romfile);
+ return;
+ }
+ memory_region_add_subregion(&nd->slot_mem, NUBUS_SLOT_SIZE - size,
+ &nd->decl_rom);
}
-
- g_free(name);
- nubus_register_format_block(nd);
}
+static Property nubus_device_properties[] = {
+ DEFINE_PROP_INT32("slot", NubusDevice, slot, -1),
+ DEFINE_PROP_STRING("romfile", NubusDevice, romfile),
+ DEFINE_PROP_END_OF_LIST()
+};
+
static void nubus_device_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
dc->realize = nubus_device_realize;
dc->bus_type = TYPE_NUBUS_BUS;
+ device_class_set_props(dc, nubus_device_properties);
}
static const TypeInfo nubus_device_type_info = {
diff --git a/hw/nubus/trace-events b/hw/nubus/trace-events
new file mode 100644
index 0000000..e31833d
--- /dev/null
+++ b/hw/nubus/trace-events
@@ -0,0 +1,7 @@
+# See docs/devel/tracing.txt for syntax documentation.
+
+# nubus-bus.c
+nubus_slot_read(uint64_t addr, int size) "reading unassigned addr 0x%"PRIx64 " size %d"
+nubus_slot_write(uint64_t addr, uint64_t val, int size) "writing unassigned addr 0x%"PRIx64 " value 0x%"PRIx64 " size %d"
+nubus_super_slot_read(uint64_t addr, int size) "reading unassigned addr 0x%"PRIx64 " size %d"
+nubus_super_slot_write(uint64_t addr, uint64_t val, int size) "writing unassigned addr 0x%"PRIx64 " value 0x%"PRIx64 " size %d"
diff --git a/hw/nubus/trace.h b/hw/nubus/trace.h
new file mode 100644
index 0000000..3749420
--- /dev/null
+++ b/hw/nubus/trace.h
@@ -0,0 +1 @@
+#include "trace/trace-hw_nubus.h"
diff --git a/include/hw/nubus/mac-nubus-bridge.h b/include/hw/nubus/mac-nubus-bridge.h
index 36aa098..70ab50a 100644
--- a/include/hw/nubus/mac-nubus-bridge.h
+++ b/include/hw/nubus/mac-nubus-bridge.h
@@ -12,13 +12,18 @@
#include "hw/nubus/nubus.h"
#include "qom/object.h"
+#define MAC_NUBUS_FIRST_SLOT 0x9
+#define MAC_NUBUS_LAST_SLOT 0xe
+#define MAC_NUBUS_SLOT_NB (MAC_NUBUS_LAST_SLOT - MAC_NUBUS_FIRST_SLOT + 1)
+
#define TYPE_MAC_NUBUS_BRIDGE "mac-nubus-bridge"
-OBJECT_DECLARE_SIMPLE_TYPE(MacNubusState, MAC_NUBUS_BRIDGE)
+OBJECT_DECLARE_SIMPLE_TYPE(MacNubusBridge, MAC_NUBUS_BRIDGE)
-struct MacNubusState {
- SysBusDevice sysbus_dev;
+struct MacNubusBridge {
+ NubusBridge parent_obj;
- NubusBus *bus;
+ MemoryRegion super_slot_alias;
+ MemoryRegion slot_alias;
};
#endif
diff --git a/include/hw/nubus/nubus.h b/include/hw/nubus/nubus.h
index e2b5cf2..b3b4d2e 100644
--- a/include/hw/nubus/nubus.h
+++ b/include/hw/nubus/nubus.h
@@ -10,17 +10,23 @@
#define HW_NUBUS_NUBUS_H
#include "hw/qdev-properties.h"
+#include "hw/sysbus.h"
#include "exec/address-spaces.h"
#include "qom/object.h"
+#include "qemu/units.h"
#define NUBUS_SUPER_SLOT_SIZE 0x10000000U
-#define NUBUS_SUPER_SLOT_NB 0x9
+#define NUBUS_SUPER_SLOT_NB 0xe
+
+#define NUBUS_SLOT_BASE (NUBUS_SUPER_SLOT_SIZE * \
+ (NUBUS_SUPER_SLOT_NB + 1))
#define NUBUS_SLOT_SIZE 0x01000000
-#define NUBUS_SLOT_NB 0xF
+#define NUBUS_FIRST_SLOT 0x0
+#define NUBUS_LAST_SLOT 0xf
+#define NUBUS_SLOT_NB (NUBUS_LAST_SLOT - NUBUS_FIRST_SLOT + 1)
-#define NUBUS_FIRST_SLOT 0x9
-#define NUBUS_LAST_SLOT 0xF
+#define NUBUS_IRQS 16
#define TYPE_NUBUS_DEVICE "nubus-device"
OBJECT_DECLARE_SIMPLE_TYPE(NubusDevice, NUBUS_DEVICE)
@@ -29,40 +35,41 @@ OBJECT_DECLARE_SIMPLE_TYPE(NubusDevice, NUBUS_DEVICE)
OBJECT_DECLARE_SIMPLE_TYPE(NubusBus, NUBUS_BUS)
#define TYPE_NUBUS_BRIDGE "nubus-bridge"
+OBJECT_DECLARE_SIMPLE_TYPE(NubusBridge, NUBUS_BRIDGE);
struct NubusBus {
BusState qbus;
+ AddressSpace nubus_as;
+ MemoryRegion nubus_mr;
+
MemoryRegion super_slot_io;
MemoryRegion slot_io;
- int current_slot;
+ uint16_t slot_available_mask;
+
+ qemu_irq irqs[NUBUS_IRQS];
};
+#define NUBUS_DECL_ROM_MAX_SIZE (128 * KiB)
+
struct NubusDevice {
DeviceState qdev;
- int slot_nb;
+ int32_t slot;
+ MemoryRegion super_slot_mem;
MemoryRegion slot_mem;
- /* Format Block */
-
- MemoryRegion fblock_io;
+ char *romfile;
+ MemoryRegion decl_rom;
+};
- uint32_t rom_length;
- uint32_t rom_crc;
- uint8_t rom_rev;
- uint8_t rom_format;
- uint8_t byte_lanes;
- int32_t directory_offset;
+void nubus_set_irq(NubusDevice *nd, int level);
- /* ROM */
+struct NubusBridge {
+ SysBusDevice parent_obj;
- MemoryRegion rom_io;
- const uint8_t *rom;
+ NubusBus bus;
};
-void nubus_register_rom(NubusDevice *dev, const uint8_t *rom, uint32_t size,
- int revision, int format, uint8_t byte_lanes);
-
#endif
diff --git a/meson.build b/meson.build
index 15ef4d3..7bdbbbd 100644
--- a/meson.build
+++ b/meson.build
@@ -2142,6 +2142,7 @@ if have_system
'hw/misc/macio',
'hw/net',
'hw/net/can',
+ 'hw/nubus',
'hw/nvme',
'hw/nvram',
'hw/pci',