@@ -35,6 +35,7 @@ devices-dirs-$(CONFIG_SOFTMMU) += watchdog/
devices-dirs-$(CONFIG_SOFTMMU) += xen/
devices-dirs-$(CONFIG_MEM_HOTPLUG) += mem/
devices-dirs-$(CONFIG_SOFTMMU) += smbios/
+devices-dirs-$(CONFIG_NUBUS) += nubus/
devices-dirs-y += core/
common-obj-y += $(devices-dirs-y)
obj-y += $(devices-dirs-y)
@@ -14,9 +14,12 @@
#include "hw/sysbus.h"
#include "ui/console.h"
#include "ui/pixel_ops.h"
+#include "hw/nubus/nubus.h"
+
+#define VIDEO_BASE 0x00001000
+#define DAFB_BASE 0x00800000
struct MacfbState {
- SysBusDevice busdev;
MemoryRegion mem_vram;
MemoryRegion mem_ctrl;
QemuConsole *con;
@@ -219,10 +222,10 @@ static void macfb_init(DeviceState *dev, MacfbState *s)
s->con = graphic_console_init(dev, 0, &macfb_ops, s);
- memory_region_init_io(&s->mem_ctrl, NULL, &macfb_ctrl_ops, s, "ctrl",
+ memory_region_init_io(&s->mem_ctrl, NULL, &macfb_ctrl_ops, s, "macfb-ctrl",
0x1000);
- memory_region_init_ram_ptr(&s->mem_vram, NULL, "vram", MACFB_VRAM_SIZE,
- s->vram);
+ memory_region_init_ram_ptr(&s->mem_vram, NULL, "macfb-vram",
+ MACFB_VRAM_SIZE, s->vram);
vmstate_register_ram(&s->mem_vram, dev);
memory_region_set_coalescing(&s->mem_vram);
}
@@ -232,6 +235,11 @@ typedef struct {
MacfbState macfb;
} MacfbSysBusState;
+typedef struct {
+ NubusDevice busdev;
+ MacfbState macfb;
+} MacfbNubusState;
+
static int macfb_sysbus_init(SysBusDevice *dev)
{
MacfbState *s = &MACFB(dev)->macfb;
@@ -243,12 +251,34 @@ static int macfb_sysbus_init(SysBusDevice *dev)
return 0;
}
+const uint8_t macfb_rom[] = {
+ 255, 0, 0, 0,
+};
+
+static int macfb_nubus_init(NubusDevice *dev)
+{
+ MacfbState *s = &DO_UPCAST(MacfbNubusState, busdev, dev)->macfb;
+
+ macfb_init(DEVICE(dev), s);
+ nubus_add_slot_mmio(dev, DAFB_BASE, &s->mem_ctrl);
+ nubus_add_slot_mmio(dev, VIDEO_BASE, &s->mem_vram);
+ nubus_register_rom(dev, macfb_rom, sizeof(macfb_rom), 1, 9, 0xf);
+
+ return 0;
+}
+
static void macfb_sysbus_reset(DeviceState *d)
{
MacfbSysBusState *s = MACFB(d);
macfb_reset(&s->macfb);
}
+static void macfb_nubus_reset(DeviceState *d)
+{
+ MacfbNubusState *s = DO_UPCAST(MacfbNubusState, busdev.qdev, d);
+ macfb_reset(&s->macfb);
+}
+
static Property macfb_sysbus_properties[] = {
DEFINE_PROP_UINT32("width", MacfbSysBusState, macfb.width, 640),
DEFINE_PROP_UINT32("height", MacfbSysBusState, macfb.height, 480),
@@ -256,18 +286,37 @@ static Property macfb_sysbus_properties[] = {
DEFINE_PROP_END_OF_LIST(),
};
+static Property macfb_nubus_properties[] = {
+ DEFINE_PROP_UINT32("width", MacfbNubusState, macfb.width, 640),
+ DEFINE_PROP_UINT32("height", MacfbNubusState, macfb.height, 480),
+ DEFINE_PROP_UINT8("depth", MacfbNubusState, macfb.depth, 8),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
static void macfb_sysbus_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
k->init = macfb_sysbus_init;
- dc->desc = "Macintosh framebuffer";
+ dc->desc = "SysBus Macintosh framebuffer";
dc->reset = macfb_sysbus_reset;
dc->vmsd = &vmstate_macfb;
dc->props = macfb_sysbus_properties;
}
+static void macfb_nubus_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ NubusDeviceClass *k = NUBUS_DEVICE_CLASS(klass);
+
+ k->init = macfb_nubus_init;
+ dc->desc = "Nubus Macintosh framebuffer";
+ dc->reset = macfb_nubus_reset;
+ dc->vmsd = &vmstate_macfb;
+ dc->props = macfb_nubus_properties;
+}
+
static TypeInfo macfb_sysbus_info = {
.name = TYPE_MACFB,
.parent = TYPE_SYS_BUS_DEVICE,
@@ -275,9 +324,17 @@ static TypeInfo macfb_sysbus_info = {
.class_init = macfb_sysbus_class_init,
};
+static TypeInfo macfb_nubus_info = {
+ .name = "nubus-macfb",
+ .parent = TYPE_NUBUS_DEVICE,
+ .instance_size = sizeof(MacfbNubusState),
+ .class_init = macfb_nubus_class_init,
+};
+
static void macfb_register_types(void)
{
type_register_static(&macfb_sysbus_info);
+ type_register_static(&macfb_nubus_info);
}
type_init(macfb_register_types)
new file mode 100644
@@ -0,0 +1,4 @@
+common-obj-y += nubus-device.o
+common-obj-y += nubus-bus.o
+common-obj-y += nubus-bridge.o
+common-obj-$(CONFIG_MAC) += mac.o
new file mode 100644
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "hw/nubus/mac.h"
+
+static void mac_nubus_slot_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned int size)
+{
+}
+
+
+static uint64_t mac_nubus_slot_read(void *opaque, hwaddr addr,
+ unsigned int size)
+{
+ return 0;
+}
+
+static const MemoryRegionOps mac_nubus_slot_ops = {
+ .read = mac_nubus_slot_read,
+ .write = mac_nubus_slot_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .valid = {
+ .min_access_size = 1,
+ .max_access_size = 1,
+ },
+};
+
+static void mac_nubus_super_slot_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned int size)
+{
+}
+
+static uint64_t mac_nubus_super_slot_read(void *opaque, hwaddr addr,
+ unsigned int size)
+{
+ return 0;
+}
+
+static const MemoryRegionOps mac_nubus_super_slot_ops = {
+ .read = mac_nubus_super_slot_read,
+ .write = mac_nubus_super_slot_write,
+ .endianness = DEVICE_BIG_ENDIAN,
+ .valid = {
+ .min_access_size = 1,
+ .max_access_size = 1,
+ },
+};
+
+static int mac_nubus_initfn(SysBusDevice *dev)
+{
+ MacNubusState *s = DO_UPCAST(MacNubusState, sysbus_dev, dev);
+ MemoryRegion *super_slot_io = g_malloc(sizeof(MemoryRegion));;
+ MemoryRegion *slot_io = g_malloc(sizeof(MemoryRegion));
+
+ memory_region_init_io(super_slot_io, NULL, &mac_nubus_super_slot_ops,
+ s, "nubus-super-slots",
+ NUBUS_SUPER_SLOT_NB * NUBUS_SUPER_SLOT_SIZE);
+
+ memory_region_init_io(slot_io, NULL, &mac_nubus_slot_ops,
+ s, "nubus-slots",
+ NUBUS_SLOT_NB * NUBUS_SLOT_SIZE);
+
+ sysbus_init_mmio(dev, super_slot_io);
+ sysbus_init_mmio(dev, slot_io);
+
+ s->bus = nubus_bus_new(DEVICE(s), super_slot_io, slot_io);
+
+ return 0;
+}
+
+static void mac_nubus_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = mac_nubus_initfn;
+ dc->desc = "Nubus bridge";
+}
+
+static const TypeInfo mac_nubus_type_info = {
+ .name = TYPE_MAC_NUBUS_BRIDGE,
+ .parent = TYPE_NUBUS_BRIDGE,
+ .instance_size = sizeof(MacNubusState),
+ .class_init = mac_nubus_class_init,
+};
+
+
+NubusBus *nubus_mac_new(hwaddr super_slot_base, hwaddr slot_base)
+{
+ DeviceState *dev;
+
+ dev = qdev_create(NULL, TYPE_MAC_NUBUS_BRIDGE);
+ qdev_init_nofail(dev);
+ sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, super_slot_base);
+ sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, slot_base);
+
+ return MAC_NUBUS_BRIDGE(dev)->bus;
+}
+
+static void mac_nubus_register_types(void)
+{
+ type_register_static(&mac_nubus_type_info);
+}
+
+type_init(mac_nubus_register_types)
new file mode 100644
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "hw/nubus/nubus.h"
+
+static void nubus_bridge_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->fw_name = "nubus";
+}
+
+static const TypeInfo nubus_bridge_info = {
+ .name = TYPE_NUBUS_BRIDGE,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(SysBusDevice),
+ .class_init = nubus_bridge_class_init,
+};
+
+static void nubus_register_types(void)
+{
+ type_register_static(&nubus_bridge_info);
+}
+
+type_init(nubus_register_types)
new file mode 100644
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "hw/nubus/nubus.h"
+
+static NubusBus *nubus;
+
+static void nubus_bus_initfn(Object *obj)
+{
+ NubusBus *bus = NUBUS_BUS(obj);;
+ bus->current_slot = NUBUS_FIRST_SLOT;
+}
+
+static void nubus_bus_class_init(ObjectClass *klass, void *data)
+{
+}
+
+static const TypeInfo nubus_bus_info = {
+ .name = TYPE_NUBUS_BUS,
+ .parent = TYPE_BUS,
+ .instance_size = sizeof(NubusBus),
+ .instance_init = nubus_bus_initfn,
+ .class_init = nubus_bus_class_init,
+};
+
+NubusBus *nubus_bus_new(DeviceState *dev, MemoryRegion *super_slot_io,
+ MemoryRegion *slot_io)
+{
+ if (nubus) {
+ fprintf(stderr, "Can't create a second Nubus bus\n");
+ return NULL;
+ }
+
+ if (NULL == dev) {
+ dev = qdev_create(NULL, "nubus-bridge");
+ qdev_init_nofail(dev);
+ }
+
+ nubus = NUBUS_BUS(qbus_create(TYPE_NUBUS_BUS, dev, NULL));
+
+ nubus->super_slot_io = super_slot_io;
+ nubus->slot_io = slot_io;
+
+ return nubus;
+}
+
+static void nubus_register_types(void)
+{
+ type_register_static(&nubus_bus_info);
+}
+
+type_init(nubus_register_types)
new file mode 100644
@@ -0,0 +1,275 @@
+/*
+ * 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.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "hw/nubus/nubus.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_NATIVE_ENDIAN,
+ .valid = {
+ .min_access_size = 1,
+ .max_access_size = 1,
+ }
+};
+
+static void nubus_register_format_block(NubusDevice *dev)
+{
+ char fblock_name[27];
+ NubusBus *bus = nubus_bus_from_device(dev);
+
+ sprintf(fblock_name, "nubus-slot-%d-format-block", dev->slot_nb);
+
+ hwaddr fblock_offset = (dev->slot_nb + 1) * NUBUS_SLOT_SIZE - FBLOCK_SIZE;
+ memory_region_init_io(&dev->fblock_io, NULL, &nubus_format_block_ops,
+ dev, fblock_name, FBLOCK_SIZE);
+ memory_region_add_subregion(bus->slot_io, fblock_offset,
+ &dev->fblock_io);
+}
+
+NubusDevice *nubus_create(NubusBus *bus, const char *name)
+{
+ DeviceState *dev;
+ NubusDevice *d;
+
+ if (!bus) {
+ hw_error("Tried to create nubus device %s with no nubus bus present.",
+ name);
+ }
+
+ if (bus->current_slot < NUBUS_FIRST_SLOT ||
+ bus->current_slot > NUBUS_LAST_SLOT) {
+ fprintf(stderr, "Cannot register nubus card '%s', not enough slot\n",
+ name);
+ return NULL;
+ }
+
+ dev = qdev_create(&bus->qbus, name);
+
+ d = NUBUS_DEVICE(dev);
+ d->slot_nb = bus->current_slot++;
+ nubus_register_format_block(d);
+
+ return d;
+}
+
+NubusDevice *nubus_try_create(NubusBus *bus, const char *name)
+{
+ DeviceState *dev;
+ NubusDevice *d;
+
+ if (!bus) {
+ hw_error("Tried to create nubus device %s with no nubus bus present.",
+ name);
+ }
+
+ if (bus->current_slot < NUBUS_FIRST_SLOT ||
+ bus->current_slot > NUBUS_LAST_SLOT) {
+ fprintf(stderr, "Cannot register nubus card '%s', not enough slot\n",
+ name);
+ return NULL;
+ }
+
+ dev = qdev_try_create(&bus->qbus, name);
+ if (!dev) {
+ return NULL;
+ }
+
+ d = NUBUS_DEVICE(dev);
+ d->slot_nb = bus->current_slot++;
+ nubus_register_format_block(d);
+
+ return d;
+}
+
+NubusDevice *nubus_create_simple(NubusBus *bus, const char *name)
+{
+ NubusDevice *dev;
+
+ dev = nubus_create(bus, name);
+ qdev_init_nofail(&dev->qdev);
+
+ return dev;
+}
+
+void nubus_add_slot_mmio(NubusDevice *dev,
+ hwaddr offset,
+ MemoryRegion *subregion)
+{
+ NubusBus *bus = nubus_bus_from_device(dev);
+ hwaddr slot_offset = dev->slot_nb * NUBUS_SLOT_SIZE + offset;
+ memory_region_add_subregion(bus->slot_io, slot_offset, subregion);
+}
+
+void nubus_add_super_slot_mmio(NubusDevice *dev,
+ hwaddr offset,
+ MemoryRegion *subregion)
+{
+ NubusBus *bus = nubus_bus_from_device(dev);
+ hwaddr slot_offset = (dev->slot_nb - 6) * NUBUS_SUPER_SLOT_SIZE + offset;
+ memory_region_add_subregion(bus->super_slot_io, slot_offset, subregion);
+}
+
+static void mac_nubus_rom_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned int size)
+{
+}
+
+static uint64_t mac_nubus_rom_read(void *opaque, hwaddr addr,
+ unsigned int size)
+{
+ NubusDevice *dev = opaque;
+
+ return dev->rom[addr];
+}
+
+static const MemoryRegionOps mac_nubus_rom_ops = {
+ .read = mac_nubus_rom_read,
+ .write = mac_nubus_rom_write,
+ .endianness = DEVICE_NATIVE_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)
+{
+ NubusBus *bus = nubus_bus_from_device(dev);
+ hwaddr rom_offset;
+ char rom_name[18];
+
+ /* 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;
+ sprintf(rom_name, "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 = (dev->slot_nb + 1) * NUBUS_SLOT_SIZE - FBLOCK_SIZE +
+ dev->directory_offset;
+ memory_region_add_subregion(bus->slot_io, rom_offset, &dev->rom_io);
+
+}
+
+
+static void nubus_device_init(Object *obj)
+{
+}
+
+static int nubus_qdev_init(DeviceState *qdev)
+{
+ NubusDevice *dev = NUBUS_DEVICE(qdev);
+ NubusDeviceClass *klass = NUBUS_DEVICE_GET_CLASS(dev);
+
+ if (klass->init) {
+ return klass->init(dev);
+ }
+
+ return 0;
+}
+
+static void nubus_device_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *k = DEVICE_CLASS(klass);
+ k->init = nubus_qdev_init;
+ k->bus_type = TYPE_NUBUS_BUS;
+}
+
+static const TypeInfo nubus_device_type_info = {
+ .name = TYPE_NUBUS_DEVICE,
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(NubusDevice),
+ .instance_init = nubus_device_init,
+ .abstract = true,
+ .class_size = sizeof(NubusDeviceClass),
+ .class_init = nubus_device_class_init,
+};
+
+static void nubus_register_types(void)
+{
+ type_register_static(&nubus_device_type_info);
+}
+
+type_init(nubus_register_types)
new file mode 100644
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef HW_NUBUS_MAC_H
+#define HW_NUBUS_MAC_H
+
+#include "hw/nubus/nubus.h"
+
+#define TYPE_MAC_NUBUS_BRIDGE "mac-nubus-bridge"
+#define MAC_NUBUS_BRIDGE(obj) OBJECT_CHECK(MacNubusState, (obj), \
+ TYPE_MAC_NUBUS_BRIDGE)
+
+typedef struct MacNubusState {
+ SysBusDevice sysbus_dev;
+ NubusBus *bus;
+} MacNubusState;
+
+NubusBus *nubus_mac_new(hwaddr super_slot_base, hwaddr slot_base);
+#endif
new file mode 100644
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef HW_NUBUS_NUBUS_H
+#define HW_NUBUS_NUBUS_H
+
+#include "hw/qdev.h"
+#include "exec/address-spaces.h"
+
+#define NUBUS_SUPER_SLOT_SIZE 0x10000000U
+#define NUBUS_SUPER_SLOT_NB 0x9
+
+#define NUBUS_SLOT_SIZE 0x01000000
+#define NUBUS_SLOT_NB 0xF
+
+#define NUBUS_FIRST_SLOT 0x9
+#define NUBUS_LAST_SLOT 0xF
+
+#define TYPE_NUBUS_DEVICE "nubus-device"
+#define NUBUS_DEVICE(obj) \
+ OBJECT_CHECK(NubusDevice, (obj), TYPE_NUBUS_DEVICE)
+#define NUBUS_DEVICE_CLASS(klass) \
+ OBJECT_CLASS_CHECK(NubusDeviceClass, (klass), TYPE_NUBUS_DEVICE)
+#define NUBUS_DEVICE_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(NubusDeviceClass, (obj), TYPE_NUBUS_DEVICE)
+
+#define TYPE_NUBUS_BUS "nubus-bus"
+#define NUBUS_BUS(obj) OBJECT_CHECK(NubusBus, (obj), TYPE_NUBUS_BUS)
+
+#define TYPE_NUBUS_BRIDGE "nubus-bridge"
+#define NUBUS_BRIDGE(obj) OBJECT_CHECK(NubusBridge, (obj), TYPE_NUBUS_BRIDGE)
+
+typedef struct NubusDeviceClass {
+ DeviceClass parent_class;
+ int (*init)(NubusDevice *dev);
+} NubusDeviceClass;
+
+struct NubusBus {
+ BusState qbus;
+ int current_slot;
+ MemoryRegion *super_slot_io;
+ MemoryRegion *slot_io;
+ qemu_irq *irqs;
+};
+
+struct NubusDevice {
+ DeviceState qdev;
+
+ int slot_nb;
+
+ /* Format Block */
+
+ MemoryRegion fblock_io;
+
+ uint32_t rom_length;
+ uint32_t rom_crc;
+ uint8_t rom_rev;
+ uint8_t rom_format;
+ uint8_t byte_lanes;
+ int32_t directory_offset;
+
+ /* ROM */
+
+ MemoryRegion rom_io;
+ const uint8_t *rom;
+};
+
+NubusBus *nubus_bus_new(DeviceState *dev, MemoryRegion *super_slot_io,
+ MemoryRegion *slot_io);
+NubusDevice *nubus_try_create(NubusBus *bus, const char *name);
+NubusDevice *nubus_create_simple(NubusBus *bus, const char *name);
+NubusDevice *nubus_create(NubusBus *bus, const char *name);
+void nubus_add_slot_mmio(NubusDevice *dev, hwaddr offset,
+ MemoryRegion *subregion);
+void nubus_add_super_slot_mmio(NubusDevice *dev, hwaddr offset,
+ MemoryRegion *subregion);
+void nubus_register_rom(NubusDevice *dev, const uint8_t *rom, uint32_t size,
+ int revision, int format, uint8_t byte_lanes);
+
+static inline NubusBus *nubus_bus_from_device(NubusDevice *d)
+{
+ return NUBUS_BUS(qdev_get_parent_bus(DEVICE(d)));
+}
+#endif
@@ -43,6 +43,8 @@ typedef struct I2SCodec I2SCodec;
typedef struct ISABus ISABus;
typedef struct ISADevice ISADevice;
typedef struct IsaDma IsaDma;
+typedef struct NubusBus NubusBus;
+typedef struct NubusDevice NubusDevice;
typedef struct MACAddr MACAddr;
typedef struct MachineClass MachineClass;
typedef struct MachineState MachineState;
Signed-off-by: Laurent Vivier <laurent@vivier.eu> --- hw/Makefile.objs | 1 + hw/display/macfb.c | 67 +++++++++++- hw/nubus/Makefile.objs | 4 + hw/nubus/mac.c | 112 +++++++++++++++++++ hw/nubus/nubus-bridge.c | 34 ++++++ hw/nubus/nubus-bus.c | 60 +++++++++++ hw/nubus/nubus-device.c | 275 +++++++++++++++++++++++++++++++++++++++++++++++ include/hw/nubus/mac.h | 24 +++++ include/hw/nubus/nubus.h | 89 +++++++++++++++ include/qemu/typedefs.h | 2 + 10 files changed, 663 insertions(+), 5 deletions(-) create mode 100644 hw/nubus/Makefile.objs create mode 100644 hw/nubus/mac.c create mode 100644 hw/nubus/nubus-bridge.c create mode 100644 hw/nubus/nubus-bus.c create mode 100644 hw/nubus/nubus-device.c create mode 100644 include/hw/nubus/mac.h create mode 100644 include/hw/nubus/nubus.h