diff options
-rw-r--r-- | hw/display/macfb.c | 6 | ||||
-rw-r--r-- | hw/m68k/q800.c | 26 | ||||
-rw-r--r-- | hw/nubus/mac-nubus-bridge.c | 34 | ||||
-rw-r--r-- | hw/nubus/nubus-bridge.c | 23 | ||||
-rw-r--r-- | hw/nubus/nubus-bus.c | 120 | ||||
-rw-r--r-- | hw/nubus/nubus-device.c | 227 | ||||
-rw-r--r-- | hw/nubus/trace-events | 7 | ||||
-rw-r--r-- | hw/nubus/trace.h | 1 | ||||
-rw-r--r-- | include/hw/nubus/mac-nubus-bridge.h | 13 | ||||
-rw-r--r-- | include/hw/nubus/nubus.h | 49 | ||||
-rw-r--r-- | meson.build | 1 |
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', |