aboutsummaryrefslogtreecommitdiff
path: root/hw/m68k
diff options
context:
space:
mode:
Diffstat (limited to 'hw/m68k')
-rw-r--r--hw/m68k/Kconfig1
-rw-r--r--hw/m68k/an5206.c4
-rw-r--r--hw/m68k/bootinfo.h30
-rw-r--r--hw/m68k/mcf5206.c11
-rw-r--r--hw/m68k/mcf5208.c24
-rw-r--r--hw/m68k/mcf_intc.c9
-rw-r--r--hw/m68k/next-cube.c1037
-rw-r--r--hw/m68k/next-kbd.c164
-rw-r--r--hw/m68k/q800-glue.c7
-rw-r--r--hw/m68k/q800.c19
-rw-r--r--hw/m68k/virt.c87
11 files changed, 885 insertions, 508 deletions
diff --git a/hw/m68k/Kconfig b/hw/m68k/Kconfig
index 0092cda..aff769b 100644
--- a/hw/m68k/Kconfig
+++ b/hw/m68k/Kconfig
@@ -18,6 +18,7 @@ config NEXTCUBE
depends on M68K
select FRAMEBUFFER
select ESCC
+ select EMPTY_SLOT
config Q800
bool
diff --git a/hw/m68k/an5206.c b/hw/m68k/an5206.c
index 1e8e64f..d97399b 100644
--- a/hw/m68k/an5206.c
+++ b/hw/m68k/an5206.c
@@ -14,7 +14,7 @@
#include "hw/loader.h"
#include "elf.h"
#include "qemu/error-report.h"
-#include "sysemu/qtest.h"
+#include "system/qtest.h"
#define KERNEL_LOAD_ADDR 0x10000
#define AN5206_MBAR_ADDR 0x10000000
@@ -74,7 +74,7 @@ static void an5206_init(MachineState *machine)
}
kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, &elf_entry,
- NULL, NULL, NULL, 1, EM_68K, 0, 0);
+ NULL, NULL, NULL, ELFDATA2MSB, EM_68K, 0, 0);
entry = elf_entry;
if (kernel_size < 0) {
kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL,
diff --git a/hw/m68k/bootinfo.h b/hw/m68k/bootinfo.h
index 0e6e3ee..0b3e7c4 100644
--- a/hw/m68k/bootinfo.h
+++ b/hw/m68k/bootinfo.h
@@ -1,5 +1,5 @@
/*
- * SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
+ * SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note
*
* Bootinfo tags from linux bootinfo.h and bootinfo-mac.h:
* This is an easily parsable and extendable structure containing all
@@ -14,39 +14,39 @@
#define BOOTINFO0(base, id) \
do { \
- stw_p(base, id); \
+ stw_be_p(base, id); \
base += 2; \
- stw_p(base, sizeof(struct bi_record)); \
+ stw_be_p(base, sizeof(struct bi_record)); \
base += 2; \
} while (0)
#define BOOTINFO1(base, id, value) \
do { \
- stw_p(base, id); \
+ stw_be_p(base, id); \
base += 2; \
- stw_p(base, sizeof(struct bi_record) + 4); \
+ stw_be_p(base, sizeof(struct bi_record) + 4); \
base += 2; \
- stl_p(base, value); \
+ stl_be_p(base, value); \
base += 4; \
} while (0)
#define BOOTINFO2(base, id, value1, value2) \
do { \
- stw_p(base, id); \
+ stw_be_p(base, id); \
base += 2; \
- stw_p(base, sizeof(struct bi_record) + 8); \
+ stw_be_p(base, sizeof(struct bi_record) + 8); \
base += 2; \
- stl_p(base, value1); \
+ stl_be_p(base, value1); \
base += 4; \
- stl_p(base, value2); \
+ stl_be_p(base, value2); \
base += 4; \
} while (0)
#define BOOTINFOSTR(base, id, string) \
do { \
- stw_p(base, id); \
+ stw_be_p(base, id); \
base += 2; \
- stw_p(base, \
+ stw_be_p(base, \
(sizeof(struct bi_record) + strlen(string) + \
1 /* null termination */ + 3 /* padding */) & ~3); \
base += 2; \
@@ -59,13 +59,13 @@
#define BOOTINFODATA(base, id, data, len) \
do { \
- stw_p(base, id); \
+ stw_be_p(base, id); \
base += 2; \
- stw_p(base, \
+ stw_be_p(base, \
(sizeof(struct bi_record) + len + \
2 /* length field */ + 3 /* padding */) & ~3); \
base += 2; \
- stw_p(base, len); \
+ stw_be_p(base, len); \
base += 2; \
for (unsigned i_ = 0; i_ < len; ++i_) { \
stb_p(base++, data[i_]); \
diff --git a/hw/m68k/mcf5206.c b/hw/m68k/mcf5206.c
index 183fd3c..a25e782 100644
--- a/hw/m68k/mcf5206.c
+++ b/hw/m68k/mcf5206.c
@@ -16,7 +16,7 @@
#include "hw/m68k/mcf.h"
#include "qemu/timer.h"
#include "hw/ptimer.h"
-#include "sysemu/sysemu.h"
+#include "system/system.h"
#include "hw/sysbus.h"
/* General purpose timer module. */
@@ -582,7 +582,7 @@ static const MemoryRegionOps m5206_mbar_ops = {
.write = m5206_mbar_writefn,
.valid.min_access_size = 1,
.valid.max_access_size = 4,
- .endianness = DEVICE_NATIVE_ENDIAN,
+ .endianness = DEVICE_BIG_ENDIAN,
};
static void mcf5206_mbar_realize(DeviceState *dev, Error **errp)
@@ -600,13 +600,12 @@ static void mcf5206_mbar_realize(DeviceState *dev, Error **errp)
s->uart[1] = mcf_uart_create(s->pic[13], serial_hd(1));
}
-static Property mcf5206_mbar_properties[] = {
+static const Property mcf5206_mbar_properties[] = {
DEFINE_PROP_LINK("m68k-cpu", m5206_mbar_state, cpu,
TYPE_M68K_CPU, M68kCPU *),
- DEFINE_PROP_END_OF_LIST(),
};
-static void mcf5206_mbar_class_init(ObjectClass *oc, void *data)
+static void mcf5206_mbar_class_init(ObjectClass *oc, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
@@ -614,7 +613,7 @@ static void mcf5206_mbar_class_init(ObjectClass *oc, void *data)
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
dc->desc = "MCF5206 system integration module";
dc->realize = mcf5206_mbar_realize;
- dc->reset = m5206_mbar_reset;
+ device_class_set_legacy_reset(dc, m5206_mbar_reset);
}
static const TypeInfo mcf5206_mbar_info = {
diff --git a/hw/m68k/mcf5208.c b/hw/m68k/mcf5208.c
index ec14096..75cc076 100644
--- a/hw/m68k/mcf5208.c
+++ b/hw/m68k/mcf5208.c
@@ -4,6 +4,14 @@
* Copyright (c) 2007 CodeSourcery.
*
* This code is licensed under the GPL
+ *
+ * This file models both the MCF5208 SoC, and the
+ * MCF5208EVB evaluation board. For details see
+ *
+ * "MCF5208 Reference Manual"
+ * https://www.nxp.com/docs/en/reference-manual/MCF5208RM.pdf
+ * "M5208EVB-RevB 32-bit Microcontroller User Manual"
+ * https://www.nxp.com/docs/en/reference-manual/M5208EVBUM.pdf
*/
#include "qemu/osdep.h"
@@ -18,8 +26,8 @@
#include "hw/m68k/mcf_fec.h"
#include "qemu/timer.h"
#include "hw/ptimer.h"
-#include "sysemu/sysemu.h"
-#include "sysemu/qtest.h"
+#include "system/system.h"
+#include "system/qtest.h"
#include "net/net.h"
#include "hw/boards.h"
#include "hw/loader.h"
@@ -147,7 +155,7 @@ static uint64_t m5208_timer_read(void *opaque, hwaddr addr,
static const MemoryRegionOps m5208_timer_ops = {
.read = m5208_timer_read,
.write = m5208_timer_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
+ .endianness = DEVICE_BIG_ENDIAN,
};
static uint64_t m5208_sys_read(void *opaque, hwaddr addr,
@@ -158,7 +166,7 @@ static uint64_t m5208_sys_read(void *opaque, hwaddr addr,
{
int n;
for (n = 0; n < 32; n++) {
- if (current_machine->ram_size < (2u << n)) {
+ if (current_machine->ram_size < (2ULL << n)) {
break;
}
}
@@ -184,7 +192,7 @@ static void m5208_sys_write(void *opaque, hwaddr addr,
static const MemoryRegionOps m5208_sys_ops = {
.read = m5208_sys_read,
.write = m5208_sys_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
+ .endianness = DEVICE_BIG_ENDIAN,
};
static uint64_t m5208_rcm_read(void *opaque, hwaddr addr,
@@ -216,7 +224,7 @@ static void m5208_rcm_write(void *opaque, hwaddr addr,
static const MemoryRegionOps m5208_rcm_ops = {
.read = m5208_rcm_read,
.write = m5208_rcm_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
+ .endianness = DEVICE_BIG_ENDIAN,
};
static void mcf5208_sys_init(MemoryRegion *address_space, qemu_irq *pic,
@@ -351,7 +359,7 @@ static void mcf5208evb_init(MachineState *machine)
/* Initial PC is always at offset 4 in firmware binaries */
ptr = rom_ptr(0x4, 4);
assert(ptr != NULL);
- env->pc = ldl_p(ptr);
+ env->pc = ldl_be_p(ptr);
}
/* Load kernel. */
@@ -364,7 +372,7 @@ static void mcf5208evb_init(MachineState *machine)
}
kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, &elf_entry,
- NULL, NULL, NULL, 1, EM_68K, 0, 0);
+ NULL, NULL, NULL, ELFDATA2MSB, EM_68K, 0, 0);
entry = elf_entry;
if (kernel_size < 0) {
kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL,
diff --git a/hw/m68k/mcf_intc.c b/hw/m68k/mcf_intc.c
index 1d3b34e..e3055b8 100644
--- a/hw/m68k/mcf_intc.c
+++ b/hw/m68k/mcf_intc.c
@@ -166,7 +166,7 @@ static void mcf_intc_reset(DeviceState *dev)
static const MemoryRegionOps mcf_intc_ops = {
.read = mcf_intc_read,
.write = mcf_intc_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
+ .endianness = DEVICE_BIG_ENDIAN,
};
static void mcf_intc_instance_init(Object *obj)
@@ -177,19 +177,18 @@ static void mcf_intc_instance_init(Object *obj)
sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
}
-static Property mcf_intc_properties[] = {
+static const Property mcf_intc_properties[] = {
DEFINE_PROP_LINK("m68k-cpu", mcf_intc_state, cpu,
TYPE_M68K_CPU, M68kCPU *),
- DEFINE_PROP_END_OF_LIST(),
};
-static void mcf_intc_class_init(ObjectClass *oc, void *data)
+static void mcf_intc_class_init(ObjectClass *oc, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
device_class_set_props(dc, mcf_intc_properties);
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
- dc->reset = mcf_intc_reset;
+ device_class_set_legacy_reset(dc, mcf_intc_reset);
}
static const TypeInfo mcf_intc_gate_info = {
diff --git a/hw/m68k/next-cube.c b/hw/m68k/next-cube.c
index 9f6f90d..957644b 100644
--- a/hw/m68k/next-cube.c
+++ b/hw/m68k/next-cube.c
@@ -2,6 +2,7 @@
* NeXT Cube System Driver
*
* Copyright (c) 2011 Bryce Lanham
+ * Copyright (c) 2024 Mark Cave-Ayland
*
* This code is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
@@ -11,8 +12,9 @@
#include "qemu/osdep.h"
#include "exec/hwaddr.h"
-#include "sysemu/sysemu.h"
-#include "sysemu/qtest.h"
+#include "exec/cpu-interrupt.h"
+#include "system/system.h"
+#include "system/qtest.h"
#include "hw/irq.h"
#include "hw/m68k/next-cube.h"
#include "hw/boards.h"
@@ -22,6 +24,7 @@
#include "qom/object.h"
#include "hw/char/escc.h" /* ZILOG 8530 Serial Emulation */
#include "hw/block/fdc.h"
+#include "hw/misc/empty_slot.h"
#include "hw/qdev-properties.h"
#include "qapi/error.h"
#include "qemu/error-report.h"
@@ -37,31 +40,17 @@
#define DPRINTF(fmt, ...) do { } while (0)
#endif
-#define TYPE_NEXT_MACHINE MACHINE_TYPE_NAME("next-cube")
-OBJECT_DECLARE_SIMPLE_TYPE(NeXTState, NEXT_MACHINE)
-
#define ENTRY 0x0100001e
#define RAM_SIZE 0x4000000
#define ROM_FILE "Rev_2.5_v66.bin"
-typedef struct next_dma {
- uint32_t csr;
- uint32_t saved_next;
- uint32_t saved_limit;
- uint32_t saved_start;
- uint32_t saved_stop;
+#define TYPE_NEXT_RTC "next-rtc"
+OBJECT_DECLARE_SIMPLE_TYPE(NeXTRTC, NEXT_RTC)
- uint32_t next;
- uint32_t limit;
- uint32_t start;
- uint32_t stop;
-
- uint32_t next_initbuf;
- uint32_t size;
-} next_dma;
+struct NeXTRTC {
+ SysBusDevice parent_obj;
-typedef struct NextRtc {
int8_t phase;
uint8_t ram[32];
uint8_t command;
@@ -69,18 +58,25 @@ typedef struct NextRtc {
uint8_t status;
uint8_t control;
uint8_t retval;
-} NextRtc;
-struct NeXTState {
- MachineState parent;
+ qemu_irq data_out_irq;
+ qemu_irq power_irq;
+};
- MemoryRegion rom;
- MemoryRegion rom2;
- MemoryRegion dmamem;
- MemoryRegion bmapm1;
- MemoryRegion bmapm2;
+#define TYPE_NEXT_SCSI "next-scsi"
+OBJECT_DECLARE_SIMPLE_TYPE(NeXTSCSI, NEXT_SCSI)
- next_dma dma[10];
+/* NeXT SCSI Controller */
+struct NeXTSCSI {
+ SysBusDevice parent_obj;
+
+ MemoryRegion scsi_mem;
+
+ SysBusESPState sysbus_esp;
+
+ MemoryRegion scsi_csr_mem;
+ uint8_t scsi_csr_1;
+ uint8_t scsi_csr_2;
};
#define TYPE_NEXT_PC "next-pc"
@@ -92,6 +88,9 @@ struct NeXTPC {
M68kCPU *cpu;
+ MemoryRegion floppy_mem;
+ MemoryRegion timer_mem;
+ MemoryRegion dummyen_mem;
MemoryRegion mmiomem;
MemoryRegion scrmem;
@@ -101,13 +100,49 @@ struct NeXTPC {
uint32_t int_mask;
uint32_t int_status;
uint32_t led;
- uint8_t scsi_csr_1;
- uint8_t scsi_csr_2;
+
+ NeXTSCSI next_scsi;
qemu_irq scsi_reset;
qemu_irq scsi_dma;
- NextRtc rtc;
+ ESCCState escc;
+
+ NeXTRTC rtc;
+ qemu_irq rtc_data_irq;
+ qemu_irq rtc_cmd_reset_irq;
+};
+
+typedef struct next_dma {
+ uint32_t csr;
+
+ uint32_t saved_next;
+ uint32_t saved_limit;
+ uint32_t saved_start;
+ uint32_t saved_stop;
+
+ uint32_t next;
+ uint32_t limit;
+ uint32_t start;
+ uint32_t stop;
+
+ uint32_t next_initbuf;
+ uint32_t size;
+} next_dma;
+
+#define TYPE_NEXT_MACHINE MACHINE_TYPE_NAME("next-cube")
+OBJECT_DECLARE_SIMPLE_TYPE(NeXTState, NEXT_MACHINE)
+
+struct NeXTState {
+ MachineState parent;
+
+ MemoryRegion rom;
+ MemoryRegion rom2;
+ MemoryRegion dmamem;
+ MemoryRegion bmapm1;
+ MemoryRegion bmapm2;
+
+ next_dma dma[10];
};
/* Thanks to NeXT forums for this */
@@ -144,120 +179,26 @@ static void next_scr2_led_update(NeXTPC *s)
static void next_scr2_rtc_update(NeXTPC *s)
{
- uint8_t old_scr2, scr2_2;
- NextRtc *rtc = &s->rtc;
+ uint8_t old_scr2_rtc, scr2_rtc;
- old_scr2 = extract32(s->old_scr2, 8, 8);
- scr2_2 = extract32(s->scr2, 8, 8);
+ old_scr2_rtc = extract32(s->old_scr2, 8, 8);
+ scr2_rtc = extract32(s->scr2, 8, 8);
- if (scr2_2 & 0x1) {
+ if (scr2_rtc & 0x1) {
/* DPRINTF("RTC %x phase %i\n", scr2_2, rtc->phase); */
- if (rtc->phase == -1) {
- rtc->phase = 0;
- }
/* If we are in going down clock... do something */
- if (((old_scr2 & SCR2_RTCLK) != (scr2_2 & SCR2_RTCLK)) &&
- ((scr2_2 & SCR2_RTCLK) == 0)) {
- if (rtc->phase < 8) {
- rtc->command = (rtc->command << 1) |
- ((scr2_2 & SCR2_RTDATA) ? 1 : 0);
- }
- if (rtc->phase >= 8 && rtc->phase < 16) {
- rtc->value = (rtc->value << 1) |
- ((scr2_2 & SCR2_RTDATA) ? 1 : 0);
-
- /* if we read RAM register, output RT_DATA bit */
- if (rtc->command <= 0x1F) {
- scr2_2 = scr2_2 & (~SCR2_RTDATA);
- if (rtc->ram[rtc->command] & (0x80 >> (rtc->phase - 8))) {
- scr2_2 |= SCR2_RTDATA;
- }
-
- rtc->retval = (rtc->retval << 1) |
- ((scr2_2 & SCR2_RTDATA) ? 1 : 0);
- }
- /* read the status 0x30 */
- if (rtc->command == 0x30) {
- scr2_2 = scr2_2 & (~SCR2_RTDATA);
- /* for now status = 0x98 (new rtc + FTU) */
- if (rtc->status & (0x80 >> (rtc->phase - 8))) {
- scr2_2 |= SCR2_RTDATA;
- }
-
- rtc->retval = (rtc->retval << 1) |
- ((scr2_2 & SCR2_RTDATA) ? 1 : 0);
- }
- /* read the status 0x31 */
- if (rtc->command == 0x31) {
- scr2_2 = scr2_2 & (~SCR2_RTDATA);
- if (rtc->control & (0x80 >> (rtc->phase - 8))) {
- scr2_2 |= SCR2_RTDATA;
- }
- rtc->retval = (rtc->retval << 1) |
- ((scr2_2 & SCR2_RTDATA) ? 1 : 0);
- }
-
- if ((rtc->command >= 0x20) && (rtc->command <= 0x2F)) {
- scr2_2 = scr2_2 & (~SCR2_RTDATA);
- /* for now 0x00 */
- time_t time_h = time(NULL);
- struct tm *info = localtime(&time_h);
- int ret = 0;
-
- switch (rtc->command) {
- case 0x20:
- ret = SCR2_TOBCD(info->tm_sec);
- break;
- case 0x21:
- ret = SCR2_TOBCD(info->tm_min);
- break;
- case 0x22:
- ret = SCR2_TOBCD(info->tm_hour);
- break;
- case 0x24:
- ret = SCR2_TOBCD(info->tm_mday);
- break;
- case 0x25:
- ret = SCR2_TOBCD((info->tm_mon + 1));
- break;
- case 0x26:
- ret = SCR2_TOBCD((info->tm_year - 100));
- break;
-
- }
-
- if (ret & (0x80 >> (rtc->phase - 8))) {
- scr2_2 |= SCR2_RTDATA;
- }
- rtc->retval = (rtc->retval << 1) |
- ((scr2_2 & SCR2_RTDATA) ? 1 : 0);
- }
-
- }
-
- rtc->phase++;
- if (rtc->phase == 16) {
- if (rtc->command >= 0x80 && rtc->command <= 0x9F) {
- rtc->ram[rtc->command - 0x80] = rtc->value;
- }
- /* write to x30 register */
- if (rtc->command == 0xB1) {
- /* clear FTU */
- if (rtc->value & 0x04) {
- rtc->status = rtc->status & (~0x18);
- s->int_status = s->int_status & (~0x04);
- }
- }
+ if (((old_scr2_rtc & SCR2_RTCLK) != (scr2_rtc & SCR2_RTCLK)) &&
+ ((scr2_rtc & SCR2_RTCLK) == 0)) {
+ if (scr2_rtc & SCR2_RTDATA) {
+ qemu_irq_raise(s->rtc_data_irq);
+ } else {
+ qemu_irq_lower(s->rtc_data_irq);
}
}
} else {
/* else end or abort */
- rtc->phase = -1;
- rtc->command = 0;
- rtc->value = 0;
+ qemu_irq_raise(s->rtc_cmd_reset_irq);
}
-
- s->scr2 = deposit32(s->scr2, 8, 8, scr2_2);
}
static uint64_t next_mmio_read(void *opaque, hwaddr addr, unsigned size)
@@ -266,30 +207,26 @@ static uint64_t next_mmio_read(void *opaque, hwaddr addr, unsigned size)
uint64_t val;
switch (addr) {
- case 0x7000:
+ case 0x2000: /* 0x2007000 */
/* DPRINTF("Read INT status: %x\n", s->int_status); */
val = s->int_status;
break;
- case 0x7800:
+ case 0x2800: /* 0x2007800 */
DPRINTF("MMIO Read INT mask: %x\n", s->int_mask);
val = s->int_mask;
break;
- case 0xc000 ... 0xc003:
- val = extract32(s->scr1, (4 - (addr - 0xc000) - size) << 3,
+ case 0x7000 ... 0x7003: /* 0x200c000 */
+ val = extract32(s->scr1, (4 - (addr - 0x7000) - size) << 3,
size << 3);
break;
- case 0xd000 ... 0xd003:
- val = extract32(s->scr2, (4 - (addr - 0xd000) - size) << 3,
+ case 0x8000 ... 0x8003: /* 0x200d000 */
+ val = extract32(s->scr2, (4 - (addr - 0x8000) - size) << 3,
size << 3);
break;
- case 0x14020:
- val = 0x7f;
- break;
-
default:
val = 0;
DPRINTF("MMIO Read @ 0x%"HWADDR_PRIx" size %d\n", addr, size);
@@ -305,25 +242,25 @@ static void next_mmio_write(void *opaque, hwaddr addr, uint64_t val,
NeXTPC *s = NEXT_PC(opaque);
switch (addr) {
- case 0x7000:
+ case 0x2000: /* 0x2007000 */
DPRINTF("INT Status old: %x new: %x\n", s->int_status,
(unsigned int)val);
s->int_status = val;
break;
- case 0x7800:
+ case 0x2800: /* 0x2007800 */
DPRINTF("INT Mask old: %x new: %x\n", s->int_mask, (unsigned int)val);
s->int_mask = val;
break;
- case 0xc000 ... 0xc003:
+ case 0x7000 ... 0x7003: /* 0x200c000 */
DPRINTF("SCR1 Write: %x\n", (unsigned int)val);
- s->scr1 = deposit32(s->scr1, (4 - (addr - 0xc000) - size) << 3,
+ s->scr1 = deposit32(s->scr1, (4 - (addr - 0x7000) - size) << 3,
size << 3, val);
break;
- case 0xd000 ... 0xd003:
- s->scr2 = deposit32(s->scr2, (4 - (addr - 0xd000) - size) << 3,
+ case 0x8000 ... 0x8003: /* 0x200d000 */
+ s->scr2 = deposit32(s->scr2, (4 - (addr - 0x8000) - size) << 3,
size << 3, val);
next_scr2_led_update(s);
next_scr2_rtc_update(s);
@@ -351,143 +288,6 @@ static const MemoryRegionOps next_mmio_ops = {
#define SCSICSR_CPUDMA 0x10 /* if set, dma enabled */
#define SCSICSR_INTMASK 0x20 /* if set, interrupt enabled */
-static uint64_t next_scr_readfn(void *opaque, hwaddr addr, unsigned size)
-{
- NeXTPC *s = NEXT_PC(opaque);
- uint64_t val;
-
- switch (addr) {
- case 0x14108:
- DPRINTF("FD read @ %x\n", (unsigned int)addr);
- val = 0x40 | 0x04 | 0x2 | 0x1;
- break;
-
- case 0x14020:
- DPRINTF("SCSI 4020 STATUS READ %X\n", s->scsi_csr_1);
- val = s->scsi_csr_1;
- break;
-
- case 0x14021:
- DPRINTF("SCSI 4021 STATUS READ %X\n", s->scsi_csr_2);
- val = 0x40;
- break;
-
- /*
- * These 4 registers are the hardware timer, not sure which register
- * is the latch instead of data, but no problems so far.
- *
- * Hack: We need to have the LSB change consistently to make it work
- */
- case 0x1a000 ... 0x1a003:
- val = extract32(clock(), (4 - (addr - 0x1a000) - size) << 3,
- size << 3);
- break;
-
- /* For now return dummy byte to allow the Ethernet test to timeout */
- case 0x6000:
- val = 0xff;
- break;
-
- default:
- DPRINTF("BMAP Read @ 0x%x size %u\n", (unsigned int)addr, size);
- val = 0;
- break;
- }
-
- return val;
-}
-
-static void next_scr_writefn(void *opaque, hwaddr addr, uint64_t val,
- unsigned size)
-{
- NeXTPC *s = NEXT_PC(opaque);
-
- switch (addr) {
- case 0x14108:
- DPRINTF("FDCSR Write: %x\n", value);
- if (val == 0x0) {
- /* qemu_irq_raise(s->fd_irq[0]); */
- }
- break;
-
- case 0x14020: /* SCSI Control Register */
- if (val & SCSICSR_FIFOFL) {
- DPRINTF("SCSICSR FIFO Flush\n");
- /* will have to add another irq to the esp if this is needed */
- /* esp_puflush_fifo(esp_g); */
- }
-
- if (val & SCSICSR_ENABLE) {
- DPRINTF("SCSICSR Enable\n");
- /*
- * qemu_irq_raise(s->scsi_dma);
- * s->scsi_csr_1 = 0xc0;
- * s->scsi_csr_1 |= 0x1;
- * qemu_irq_pulse(s->scsi_dma);
- */
- }
- /*
- * else
- * s->scsi_csr_1 &= ~SCSICSR_ENABLE;
- */
-
- if (val & SCSICSR_RESET) {
- DPRINTF("SCSICSR Reset\n");
- /* I think this should set DMADIR. CPUDMA and INTMASK to 0 */
- qemu_irq_raise(s->scsi_reset);
- s->scsi_csr_1 &= ~(SCSICSR_INTMASK | 0x80 | 0x1);
- qemu_irq_lower(s->scsi_reset);
- }
- if (val & SCSICSR_DMADIR) {
- DPRINTF("SCSICSR DMAdir\n");
- }
- if (val & SCSICSR_CPUDMA) {
- DPRINTF("SCSICSR CPUDMA\n");
- /* qemu_irq_raise(s->scsi_dma); */
- s->int_status |= 0x4000000;
- } else {
- /* fprintf(stderr,"SCSICSR CPUDMA disabled\n"); */
- s->int_status &= ~(0x4000000);
- /* qemu_irq_lower(s->scsi_dma); */
- }
- if (val & SCSICSR_INTMASK) {
- DPRINTF("SCSICSR INTMASK\n");
- /*
- * int_mask &= ~0x1000;
- * s->scsi_csr_1 |= val;
- * s->scsi_csr_1 &= ~SCSICSR_INTMASK;
- * if (s->scsi_queued) {
- * s->scsi_queued = 0;
- * next_irq(s, NEXT_SCSI_I, level);
- * }
- */
- } else {
- /* int_mask |= 0x1000; */
- }
- if (val & 0x80) {
- /* int_mask |= 0x1000; */
- /* s->scsi_csr_1 |= 0x80; */
- }
- DPRINTF("SCSICSR Write: %x\n", val);
- /* s->scsi_csr_1 = val; */
- break;
-
- /* Hardware timer latch - not implemented yet */
- case 0x1a000:
- default:
- DPRINTF("BMAP Write @ 0x%x with 0x%x size %u\n", (unsigned int)addr,
- val, size);
- }
-}
-
-static const MemoryRegionOps next_scr_ops = {
- .read = next_scr_readfn,
- .write = next_scr_writefn,
- .valid.min_access_size = 1,
- .valid.max_access_size = 4,
- .endianness = DEVICE_BIG_ENDIAN,
-};
-
#define NEXTDMA_SCSI(x) (0x10 + x)
#define NEXTDMA_FD(x) (0x10 + x)
#define NEXTDMA_ENTX(x) (0x110 + x)
@@ -585,7 +385,7 @@ static void next_dma_write(void *opaque, hwaddr addr, uint64_t val,
break;
default:
- DPRINTF("DMA write @ %x w/ %x\n", (unsigned)addr, (unsigned)value);
+ DPRINTF("DMA write @ %x w/ %x\n", (unsigned)addr, (unsigned)val);
}
}
@@ -828,84 +628,579 @@ static void nextscsi_write(void *opaque, uint8_t *buf, int size)
nextdma_write(opaque, buf, size, NEXTDMA_SCSI);
}
-static void next_scsi_init(DeviceState *pcdev, M68kCPU *cpu)
+static void next_scsi_csr_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned size)
+{
+ NeXTSCSI *s = NEXT_SCSI(opaque);
+ NeXTPC *pc = NEXT_PC(container_of(s, NeXTPC, next_scsi));
+
+ switch (addr) {
+ case 0:
+ if (val & SCSICSR_FIFOFL) {
+ DPRINTF("SCSICSR FIFO Flush\n");
+ /* will have to add another irq to the esp if this is needed */
+ /* esp_puflush_fifo(esp_g); */
+ }
+
+ if (val & SCSICSR_ENABLE) {
+ DPRINTF("SCSICSR Enable\n");
+ /*
+ * qemu_irq_raise(s->scsi_dma);
+ * s->scsi_csr_1 = 0xc0;
+ * s->scsi_csr_1 |= 0x1;
+ * qemu_irq_pulse(s->scsi_dma);
+ */
+ }
+ /*
+ * else
+ * s->scsi_csr_1 &= ~SCSICSR_ENABLE;
+ */
+
+ if (val & SCSICSR_RESET) {
+ DPRINTF("SCSICSR Reset\n");
+ /* I think this should set DMADIR. CPUDMA and INTMASK to 0 */
+ qemu_irq_raise(pc->scsi_reset);
+ s->scsi_csr_1 &= ~(SCSICSR_INTMASK | 0x80 | 0x1);
+ qemu_irq_lower(pc->scsi_reset);
+ }
+ if (val & SCSICSR_DMADIR) {
+ DPRINTF("SCSICSR DMAdir\n");
+ }
+ if (val & SCSICSR_CPUDMA) {
+ DPRINTF("SCSICSR CPUDMA\n");
+ /* qemu_irq_raise(s->scsi_dma); */
+ pc->int_status |= 0x4000000;
+ } else {
+ /* fprintf(stderr,"SCSICSR CPUDMA disabled\n"); */
+ pc->int_status &= ~(0x4000000);
+ /* qemu_irq_lower(s->scsi_dma); */
+ }
+ if (val & SCSICSR_INTMASK) {
+ DPRINTF("SCSICSR INTMASK\n");
+ /*
+ * int_mask &= ~0x1000;
+ * s->scsi_csr_1 |= val;
+ * s->scsi_csr_1 &= ~SCSICSR_INTMASK;
+ * if (s->scsi_queued) {
+ * s->scsi_queued = 0;
+ * next_irq(s, NEXT_SCSI_I, level);
+ * }
+ */
+ } else {
+ /* int_mask |= 0x1000; */
+ }
+ if (val & 0x80) {
+ /* int_mask |= 0x1000; */
+ /* s->scsi_csr_1 |= 0x80; */
+ }
+ DPRINTF("SCSICSR1 Write: %"PRIx64 "\n", val);
+ s->scsi_csr_1 = val;
+ break;
+
+ case 1:
+ DPRINTF("SCSICSR2 Write: %"PRIx64 "\n", val);
+ s->scsi_csr_2 = val;
+ break;
+
+ default:
+ g_assert_not_reached();
+ }
+}
+
+static uint64_t next_scsi_csr_read(void *opaque, hwaddr addr, unsigned size)
+{
+ NeXTSCSI *s = NEXT_SCSI(opaque);
+ uint64_t val;
+
+ switch (addr) {
+ case 0:
+ DPRINTF("SCSI 4020 STATUS READ %X\n", s->scsi_csr_1);
+ val = s->scsi_csr_1;
+ break;
+
+ case 1:
+ DPRINTF("SCSI 4021 STATUS READ %X\n", s->scsi_csr_2);
+ val = s->scsi_csr_2;
+ break;
+
+ default:
+ g_assert_not_reached();
+ }
+
+ return val;
+}
+
+static const MemoryRegionOps next_scsi_csr_ops = {
+ .read = next_scsi_csr_read,
+ .write = next_scsi_csr_write,
+ .valid.min_access_size = 1,
+ .valid.max_access_size = 1,
+ .endianness = DEVICE_BIG_ENDIAN,
+};
+
+static void next_scsi_init(Object *obj)
{
- struct NeXTPC *next_pc = NEXT_PC(pcdev);
- DeviceState *dev;
- SysBusDevice *sysbusdev;
+ NeXTSCSI *s = NEXT_SCSI(obj);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+
+ object_initialize_child(obj, "esp", &s->sysbus_esp, TYPE_SYSBUS_ESP);
+
+ memory_region_init_io(&s->scsi_csr_mem, obj, &next_scsi_csr_ops,
+ s, "csrs", 2);
+
+ memory_region_init(&s->scsi_mem, obj, "next.scsi", 0x40);
+ sysbus_init_mmio(sbd, &s->scsi_mem);
+}
+
+static void next_scsi_realize(DeviceState *dev, Error **errp)
+{
+ NeXTSCSI *s = NEXT_SCSI(dev);
SysBusESPState *sysbus_esp;
+ SysBusDevice *sbd;
ESPState *esp;
+ NeXTPC *pcdev;
+
+ pcdev = NEXT_PC(container_of(s, NeXTPC, next_scsi));
- dev = qdev_new(TYPE_SYSBUS_ESP);
- sysbus_esp = SYSBUS_ESP(dev);
+ /* ESP */
+ sysbus_esp = SYSBUS_ESP(&s->sysbus_esp);
esp = &sysbus_esp->esp;
esp->dma_memory_read = nextscsi_read;
esp->dma_memory_write = nextscsi_write;
esp->dma_opaque = pcdev;
sysbus_esp->it_shift = 0;
esp->dma_enabled = 1;
- sysbusdev = SYS_BUS_DEVICE(dev);
- sysbus_realize_and_unref(sysbusdev, &error_fatal);
- sysbus_connect_irq(sysbusdev, 0, qdev_get_gpio_in(pcdev, NEXT_SCSI_I));
- sysbus_mmio_map(sysbusdev, 0, 0x2114000);
+ sbd = SYS_BUS_DEVICE(sysbus_esp);
+ if (!sysbus_realize(sbd, errp)) {
+ return;
+ }
+ memory_region_add_subregion(&s->scsi_mem, 0x0,
+ sysbus_mmio_get_region(sbd, 0));
- next_pc->scsi_reset = qdev_get_gpio_in(dev, 0);
- next_pc->scsi_dma = qdev_get_gpio_in(dev, 1);
+ /* SCSI CSRs */
+ memory_region_add_subregion(&s->scsi_mem, 0x20, &s->scsi_csr_mem);
- scsi_bus_legacy_handle_cmdline(&esp->bus);
+ scsi_bus_legacy_handle_cmdline(&s->sysbus_esp.esp.bus);
}
-static void next_escc_init(DeviceState *pcdev)
+static const VMStateDescription next_scsi_vmstate = {
+ .name = "next-scsi",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .fields = (const VMStateField[]) {
+ VMSTATE_UINT8(scsi_csr_1, NeXTSCSI),
+ VMSTATE_UINT8(scsi_csr_2, NeXTSCSI),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+static void next_scsi_class_init(ObjectClass *klass, const void *data)
{
- DeviceState *dev;
- SysBusDevice *s;
-
- dev = qdev_new(TYPE_ESCC);
- qdev_prop_set_uint32(dev, "disabled", 0);
- qdev_prop_set_uint32(dev, "frequency", 9600 * 384);
- qdev_prop_set_uint32(dev, "it_shift", 0);
- qdev_prop_set_bit(dev, "bit_swap", true);
- qdev_prop_set_chr(dev, "chrB", serial_hd(1));
- qdev_prop_set_chr(dev, "chrA", serial_hd(0));
- qdev_prop_set_uint32(dev, "chnBtype", escc_serial);
- qdev_prop_set_uint32(dev, "chnAtype", escc_serial);
-
- s = SYS_BUS_DEVICE(dev);
- sysbus_realize_and_unref(s, &error_fatal);
- sysbus_connect_irq(s, 0, qdev_get_gpio_in(pcdev, NEXT_SCC_I));
- sysbus_connect_irq(s, 1, qdev_get_gpio_in(pcdev, NEXT_SCC_DMA_I));
- sysbus_mmio_map(s, 0, 0x2118000);
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->desc = "NeXT SCSI Controller";
+ dc->realize = next_scsi_realize;
+ dc->vmsd = &next_scsi_vmstate;
}
-static void next_pc_reset(DeviceState *dev)
+static const TypeInfo next_scsi_info = {
+ .name = TYPE_NEXT_SCSI,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_init = next_scsi_init,
+ .instance_size = sizeof(NeXTSCSI),
+ .class_init = next_scsi_class_init,
+};
+
+static void next_floppy_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned size)
{
- NeXTPC *s = NEXT_PC(dev);
+ switch (addr) {
+ case 0:
+ DPRINTF("FDCSR Write: %"PRIx64 "\n", val);
+ if (val == 0x0) {
+ /* qemu_irq_raise(s->fd_irq[0]); */
+ }
+ break;
+
+ default:
+ g_assert_not_reached();
+ }
+}
+
+static uint64_t next_floppy_read(void *opaque, hwaddr addr, unsigned size)
+{
+ uint64_t val;
+
+ switch (addr) {
+ case 0:
+ DPRINTF("FD read @ %x\n", (unsigned int)addr);
+ val = 0x40 | 0x04 | 0x2 | 0x1;
+ break;
+
+ default:
+ g_assert_not_reached();
+ }
+
+ return val;
+}
+
+static const MemoryRegionOps next_floppy_ops = {
+ .read = next_floppy_read,
+ .write = next_floppy_write,
+ .valid.min_access_size = 1,
+ .valid.max_access_size = 4,
+ .endianness = DEVICE_BIG_ENDIAN,
+};
+
+static void next_timer_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned size)
+{
+ switch (addr) {
+ case 0 ... 3:
+ /* Hardware timer latch - not implemented yet */
+ break;
+
+ default:
+ g_assert_not_reached();
+ }
+}
+
+static uint64_t next_timer_read(void *opaque, hwaddr addr, unsigned size)
+{
+ uint64_t val;
+
+ switch (addr) {
+ case 0 ... 3:
+ /*
+ * These 4 registers are the hardware timer, not sure which register
+ * is the latch instead of data, but no problems so far.
+ *
+ * Hack: We need to have the LSB change consistently to make it work
+ */
+ val = extract32(clock(), (4 - addr - size) << 3,
+ size << 3);
+ break;
+
+ default:
+ g_assert_not_reached();
+ }
+
+ return val;
+}
+
+static const MemoryRegionOps next_timer_ops = {
+ .read = next_timer_read,
+ .write = next_timer_write,
+ .valid.min_access_size = 1,
+ .valid.max_access_size = 4,
+ .endianness = DEVICE_BIG_ENDIAN,
+};
+
+static void next_dummy_en_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned size)
+{
+ /* Do nothing */
+}
+
+static uint64_t next_dummy_en_read(void *opaque, hwaddr addr, unsigned size)
+{
+ uint64_t val;
+
+ switch (addr) {
+ case 0:
+ /* For now return dummy byte to allow the Ethernet test to timeout */
+ val = 0xff;
+ break;
+
+ default:
+ val = 0;
+ }
+
+ return val;
+}
+
+static const MemoryRegionOps next_dummy_en_ops = {
+ .read = next_dummy_en_read,
+ .write = next_dummy_en_write,
+ .valid.min_access_size = 1,
+ .valid.max_access_size = 4,
+ .endianness = DEVICE_BIG_ENDIAN,
+};
+
+static bool next_rtc_cmd_is_write(uint8_t cmd)
+{
+ return (cmd >= 0x80 && cmd <= 0x9f) ||
+ (cmd == 0xb1);
+}
+
+static void next_rtc_data_in_irq(void *opaque, int n, int level)
+{
+ NeXTRTC *rtc = NEXT_RTC(opaque);
+
+ if (rtc->phase < 8) {
+ rtc->command = (rtc->command << 1) | level;
+
+ if (rtc->phase == 7 && !next_rtc_cmd_is_write(rtc->command)) {
+ if (rtc->command <= 0x1f) {
+ /* RAM registers */
+ rtc->retval = rtc->ram[rtc->command];
+ }
+ if ((rtc->command >= 0x20) && (rtc->command <= 0x2f)) {
+ /* RTC */
+ time_t time_h = time(NULL);
+ struct tm *info = localtime(&time_h);
+ rtc->retval = 0;
+
+ switch (rtc->command) {
+ case 0x20:
+ rtc->retval = SCR2_TOBCD(info->tm_sec);
+ break;
+ case 0x21:
+ rtc->retval = SCR2_TOBCD(info->tm_min);
+ break;
+ case 0x22:
+ rtc->retval = SCR2_TOBCD(info->tm_hour);
+ break;
+ case 0x24:
+ rtc->retval = SCR2_TOBCD(info->tm_mday);
+ break;
+ case 0x25:
+ rtc->retval = SCR2_TOBCD((info->tm_mon + 1));
+ break;
+ case 0x26:
+ rtc->retval = SCR2_TOBCD((info->tm_year - 100));
+ break;
+ }
+ }
+ if (rtc->command == 0x30) {
+ /* read the status 0x30 */
+ rtc->retval = rtc->status;
+ }
+ if (rtc->command == 0x31) {
+ /* read the control 0x31 */
+ rtc->retval = rtc->control;
+ }
+ }
+ }
+ if (rtc->phase >= 8 && rtc->phase < 16) {
+ if (next_rtc_cmd_is_write(rtc->command)) {
+ /* Shift in value to write */
+ rtc->value = (rtc->value << 1) | level;
+ } else {
+ /* Shift out value to read */
+ if (rtc->retval & (0x80 >> (rtc->phase - 8))) {
+ qemu_irq_raise(rtc->data_out_irq);
+ } else {
+ qemu_irq_lower(rtc->data_out_irq);
+ }
+ }
+ }
+
+ rtc->phase++;
+ if (rtc->phase == 16 && next_rtc_cmd_is_write(rtc->command)) {
+ if (rtc->command >= 0x80 && rtc->command <= 0x9f) {
+ /* RAM registers */
+ rtc->ram[rtc->command - 0x80] = rtc->value;
+ }
+ if (rtc->command == 0xb1) {
+ /* write to 0x30 register */
+ if (rtc->value & 0x04) {
+ /* clear FTU */
+ rtc->status = rtc->status & (~0x18);
+ qemu_irq_lower(rtc->power_irq);
+ }
+ }
+ }
+}
+
+static void next_rtc_cmd_reset_irq(void *opaque, int n, int level)
+{
+ NeXTRTC *rtc = NEXT_RTC(opaque);
+
+ if (level) {
+ rtc->phase = 0;
+ rtc->command = 0;
+ rtc->value = 0;
+ }
+}
+
+static void next_rtc_reset_hold(Object *obj, ResetType type)
+{
+ NeXTRTC *rtc = NEXT_RTC(obj);
+
+ rtc->status = 0x90;
+
+ /* Load RTC RAM - TODO: provide possibility to load contents from file */
+ memcpy(rtc->ram, rtc_ram2, 32);
+}
+
+static void next_rtc_init(Object *obj)
+{
+ NeXTRTC *rtc = NEXT_RTC(obj);
+
+ qdev_init_gpio_in_named(DEVICE(obj), next_rtc_data_in_irq,
+ "rtc-data-in", 1);
+ qdev_init_gpio_out_named(DEVICE(obj), &rtc->data_out_irq,
+ "rtc-data-out", 1);
+ qdev_init_gpio_in_named(DEVICE(obj), next_rtc_cmd_reset_irq,
+ "rtc-cmd-reset", 1);
+ qdev_init_gpio_out_named(DEVICE(obj), &rtc->power_irq,
+ "rtc-power-out", 1);
+}
+
+static const VMStateDescription next_rtc_vmstate = {
+ .name = "next-rtc",
+ .version_id = 3,
+ .minimum_version_id = 3,
+ .fields = (const VMStateField[]) {
+ VMSTATE_INT8(phase, NeXTRTC),
+ VMSTATE_UINT8_ARRAY(ram, NeXTRTC, 32),
+ VMSTATE_UINT8(command, NeXTRTC),
+ VMSTATE_UINT8(value, NeXTRTC),
+ VMSTATE_UINT8(status, NeXTRTC),
+ VMSTATE_UINT8(control, NeXTRTC),
+ VMSTATE_UINT8(retval, NeXTRTC),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+static void next_rtc_class_init(ObjectClass *klass, const void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
+
+ dc->desc = "NeXT RTC";
+ dc->vmsd = &next_rtc_vmstate;
+ rc->phases.hold = next_rtc_reset_hold;
+}
+
+static const TypeInfo next_rtc_info = {
+ .name = TYPE_NEXT_RTC,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_init = next_rtc_init,
+ .instance_size = sizeof(NeXTRTC),
+ .class_init = next_rtc_class_init,
+};
+
+static void next_pc_rtc_data_in_irq(void *opaque, int n, int level)
+{
+ NeXTPC *s = NEXT_PC(opaque);
+ uint8_t scr2_2 = extract32(s->scr2, 8, 8);
+
+ if (level) {
+ scr2_2 |= SCR2_RTDATA;
+ } else {
+ scr2_2 &= ~SCR2_RTDATA;
+ }
+
+ s->scr2 = deposit32(s->scr2, 8, 8, scr2_2);
+}
+
+static void next_pc_reset_hold(Object *obj, ResetType type)
+{
+ NeXTPC *s = NEXT_PC(obj);
/* Set internal registers to initial values */
/* 0x0000XX00 << vital bits */
s->scr1 = 0x00011102;
s->scr2 = 0x00ff0c80;
s->old_scr2 = s->scr2;
-
- s->rtc.status = 0x90;
-
- /* Load RTC RAM - TODO: provide possibility to load contents from file */
- memcpy(s->rtc.ram, rtc_ram2, 32);
}
static void next_pc_realize(DeviceState *dev, Error **errp)
{
NeXTPC *s = NEXT_PC(dev);
- SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+ SysBusDevice *sbd;
+ DeviceState *d;
+
+ /* SCSI */
+ sbd = SYS_BUS_DEVICE(&s->next_scsi);
+ if (!sysbus_realize(sbd, errp)) {
+ return;
+ }
- qdev_init_gpio_in(dev, next_irq, NEXT_NUM_IRQS);
+ d = DEVICE(object_resolve_path_component(OBJECT(&s->next_scsi), "esp"));
+ sysbus_connect_irq(SYS_BUS_DEVICE(d), 0,
+ qdev_get_gpio_in(DEVICE(s), NEXT_SCSI_I));
+
+ s->scsi_reset = qdev_get_gpio_in(d, 0);
+ s->scsi_dma = qdev_get_gpio_in(d, 1);
+
+ /* ESCC */
+ d = DEVICE(&s->escc);
+ qdev_prop_set_uint32(d, "disabled", 0);
+ qdev_prop_set_uint32(d, "frequency", 9600 * 384);
+ qdev_prop_set_uint32(d, "it_shift", 0);
+ qdev_prop_set_bit(d, "bit_swap", true);
+ qdev_prop_set_chr(d, "chrB", serial_hd(1));
+ qdev_prop_set_chr(d, "chrA", serial_hd(0));
+ qdev_prop_set_uint32(d, "chnBtype", escc_serial);
+ qdev_prop_set_uint32(d, "chnAtype", escc_serial);
+
+ sbd = SYS_BUS_DEVICE(d);
+ if (!sysbus_realize(sbd, errp)) {
+ return;
+ }
+ sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(dev, NEXT_SCC_I));
+ sysbus_connect_irq(sbd, 1, qdev_get_gpio_in(dev, NEXT_SCC_DMA_I));
+
+ /* RTC */
+ d = DEVICE(&s->rtc);
+ if (!sysbus_realize(SYS_BUS_DEVICE(d), errp)) {
+ return;
+ }
+ /* Data from NeXTPC to RTC */
+ qdev_connect_gpio_out_named(dev, "rtc-data-out", 0,
+ qdev_get_gpio_in_named(d, "rtc-data-in", 0));
+ /* Data from RTC to NeXTPC */
+ qdev_connect_gpio_out_named(d, "rtc-data-out", 0,
+ qdev_get_gpio_in_named(dev,
+ "rtc-data-in", 0));
+ qdev_connect_gpio_out_named(dev, "rtc-cmd-reset", 0,
+ qdev_get_gpio_in_named(d, "rtc-cmd-reset", 0));
+ qdev_connect_gpio_out_named(d, "rtc-power-out", 0,
+ qdev_get_gpio_in(dev, NEXT_PWR_I));
+}
+
+static void next_pc_init(Object *obj)
+{
+ NeXTPC *s = NEXT_PC(obj);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+
+ qdev_init_gpio_in(DEVICE(obj), next_irq, NEXT_NUM_IRQS);
memory_region_init_io(&s->mmiomem, OBJECT(s), &next_mmio_ops, s,
- "next.mmio", 0xd0000);
- memory_region_init_io(&s->scrmem, OBJECT(s), &next_scr_ops, s,
- "next.scr", 0x20000);
+ "next.mmio", 0x9000);
sysbus_init_mmio(sbd, &s->mmiomem);
- sysbus_init_mmio(sbd, &s->scrmem);
+
+ memory_region_init_io(&s->dummyen_mem, OBJECT(s), &next_dummy_en_ops, s,
+ "next.en", 0x20);
+ sysbus_init_mmio(sbd, &s->dummyen_mem);
+
+ object_initialize_child(obj, "next-scsi", &s->next_scsi, TYPE_NEXT_SCSI);
+ sysbus_init_mmio(sbd,
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->next_scsi), 0));
+
+ memory_region_init_io(&s->floppy_mem, OBJECT(s), &next_floppy_ops, s,
+ "next.floppy", 4);
+ sysbus_init_mmio(sbd, &s->floppy_mem);
+
+ object_initialize_child(obj, "escc", &s->escc, TYPE_ESCC);
+ sysbus_init_mmio(sbd,
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->escc), 0));
+
+ memory_region_init_io(&s->timer_mem, OBJECT(s), &next_timer_ops, s,
+ "next.timer", 4);
+ sysbus_init_mmio(sbd, &s->timer_mem);
+
+ object_initialize_child(obj, "rtc", &s->rtc, TYPE_NEXT_RTC);
+
+ qdev_init_gpio_in_named(DEVICE(obj), next_pc_rtc_data_in_irq,
+ "rtc-data-in", 1);
+ qdev_init_gpio_out_named(DEVICE(obj), &s->rtc_data_irq,
+ "rtc-data-out", 1);
+ qdev_init_gpio_out_named(DEVICE(obj), &s->rtc_cmd_reset_irq,
+ "rtc-cmd-reset", 1);
}
/*
@@ -914,31 +1209,14 @@ static void next_pc_realize(DeviceState *dev, Error **errp)
* this cpu link property and could instead provide outbound IRQ lines
* that the board could wire up to the CPU.
*/
-static Property next_pc_properties[] = {
+static const Property next_pc_properties[] = {
DEFINE_PROP_LINK("cpu", NeXTPC, cpu, TYPE_M68K_CPU, M68kCPU *),
- DEFINE_PROP_END_OF_LIST(),
-};
-
-static const VMStateDescription next_rtc_vmstate = {
- .name = "next-rtc",
- .version_id = 2,
- .minimum_version_id = 2,
- .fields = (const VMStateField[]) {
- VMSTATE_INT8(phase, NextRtc),
- VMSTATE_UINT8_ARRAY(ram, NextRtc, 32),
- VMSTATE_UINT8(command, NextRtc),
- VMSTATE_UINT8(value, NextRtc),
- VMSTATE_UINT8(status, NextRtc),
- VMSTATE_UINT8(control, NextRtc),
- VMSTATE_UINT8(retval, NextRtc),
- VMSTATE_END_OF_LIST()
- },
};
static const VMStateDescription next_pc_vmstate = {
.name = "next-pc",
- .version_id = 2,
- .minimum_version_id = 2,
+ .version_id = 4,
+ .minimum_version_id = 4,
.fields = (const VMStateField[]) {
VMSTATE_UINT32(scr1, NeXTPC),
VMSTATE_UINT32(scr2, NeXTPC),
@@ -946,27 +1224,26 @@ static const VMStateDescription next_pc_vmstate = {
VMSTATE_UINT32(int_mask, NeXTPC),
VMSTATE_UINT32(int_status, NeXTPC),
VMSTATE_UINT32(led, NeXTPC),
- VMSTATE_UINT8(scsi_csr_1, NeXTPC),
- VMSTATE_UINT8(scsi_csr_2, NeXTPC),
- VMSTATE_STRUCT(rtc, NeXTPC, 0, next_rtc_vmstate, NextRtc),
VMSTATE_END_OF_LIST()
},
};
-static void next_pc_class_init(ObjectClass *klass, void *data)
+static void next_pc_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
dc->desc = "NeXT Peripheral Controller";
dc->realize = next_pc_realize;
- dc->reset = next_pc_reset;
device_class_set_props(dc, next_pc_properties);
dc->vmsd = &next_pc_vmstate;
+ rc->phases.hold = next_pc_reset_hold;
}
static const TypeInfo next_pc_info = {
.name = TYPE_NEXT_PC,
.parent = TYPE_SYS_BUS_DEVICE,
+ .instance_init = next_pc_init,
.instance_size = sizeof(NeXTPC),
.class_init = next_pc_class_init,
};
@@ -1004,11 +1281,32 @@ static void next_cube_init(MachineState *machine)
sysbus_create_simple(TYPE_NEXTFB, 0x0B000000, NULL);
/* MMIO */
- sysbus_mmio_map(SYS_BUS_DEVICE(pcdev), 0, 0x02000000);
+ sysbus_mmio_map(SYS_BUS_DEVICE(pcdev), 0, 0x02005000);
/* BMAP IO - acts as a catch-all for now */
sysbus_mmio_map(SYS_BUS_DEVICE(pcdev), 1, 0x02100000);
+ /* en network (dummy) */
+ sysbus_mmio_map(SYS_BUS_DEVICE(pcdev), 1, 0x02106000);
+
+ /* unknown: Brightness control register? */
+ empty_slot_init("next.unknown.0", 0x02110000, 0x10);
+ /* unknown: Magneto-Optical drive controller? */
+ empty_slot_init("next.unknown.1", 0x02112000, 0x10);
+
+ /* SCSI */
+ sysbus_mmio_map(SYS_BUS_DEVICE(pcdev), 2, 0x02114000);
+ /* Floppy */
+ sysbus_mmio_map(SYS_BUS_DEVICE(pcdev), 3, 0x02114108);
+ /* ESCC */
+ sysbus_mmio_map(SYS_BUS_DEVICE(pcdev), 4, 0x02118000);
+
+ /* unknown: Serial clock configuration register? */
+ empty_slot_init("next.unknown.2", 0x02118004, 0x10);
+
+ /* Timer */
+ sysbus_mmio_map(SYS_BUS_DEVICE(pcdev), 5, 0x0211a000);
+
/* BMAP memory */
memory_region_init_ram_flags_nomigrate(&m->bmapm1, NULL, "next.bmapmem",
64, RAM_SHARED, &error_fatal);
@@ -1036,7 +1334,7 @@ static void next_cube_init(MachineState *machine)
/* Initial PC is always at offset 4 in firmware binaries */
ptr = rom_ptr(0x01000004, 4);
g_assert(ptr != NULL);
- env->pc = ldl_p(ptr);
+ env->pc = ldl_be_p(ptr);
if (env->pc >= 0x01020000) {
error_report("'%s' does not seem to be a valid firmware image.",
bios_name);
@@ -1044,21 +1342,13 @@ static void next_cube_init(MachineState *machine)
}
}
- /* Serial */
- next_escc_init(pcdev);
-
- /* TODO: */
- /* Network */
- /* SCSI */
- next_scsi_init(pcdev, cpu);
-
/* DMA */
memory_region_init_io(&m->dmamem, NULL, &next_dma_ops, machine,
"next.dma", 0x5000);
memory_region_add_subregion(sysmem, 0x02000000, &m->dmamem);
}
-static void next_machine_class_init(ObjectClass *oc, void *data)
+static void next_machine_class_init(ObjectClass *oc, const void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
@@ -1068,6 +1358,7 @@ static void next_machine_class_init(ObjectClass *oc, void *data)
mc->default_ram_size = RAM_SIZE;
mc->default_ram_id = "next.ram";
mc->default_cpu_type = M68K_CPU_TYPE_NAME("m68040");
+ mc->no_cdrom = true;
}
static const TypeInfo next_typeinfo = {
@@ -1081,6 +1372,8 @@ static void next_register_type(void)
{
type_register_static(&next_typeinfo);
type_register_static(&next_pc_info);
+ type_register_static(&next_scsi_info);
+ type_register_static(&next_rtc_info);
}
type_init(next_register_type)
diff --git a/hw/m68k/next-kbd.c b/hw/m68k/next-kbd.c
index 0c348c1..2bec945 100644
--- a/hw/m68k/next-kbd.c
+++ b/hw/m68k/next-kbd.c
@@ -68,7 +68,6 @@ struct NextKBDState {
uint16_t shift;
};
-static void queue_code(void *opaque, int code);
/* lots of magic numbers here */
static uint32_t kbd_read_byte(void *opaque, hwaddr addr)
@@ -163,71 +162,73 @@ static const MemoryRegionOps kbd_ops = {
.write = kbd_writefn,
.valid.min_access_size = 1,
.valid.max_access_size = 4,
- .endianness = DEVICE_NATIVE_ENDIAN,
+ .endianness = DEVICE_BIG_ENDIAN,
};
-static void nextkbd_event(void *opaque, int ch)
-{
- /*
- * Will want to set vars for caps/num lock
- * if (ch & 0x80) -> key release
- * there's also e0 escaped scancodes that might need to be handled
- */
- queue_code(opaque, ch);
-}
-
-static const unsigned char next_keycodes[128] = {
- 0x00, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x50, 0x4F,
- 0x4E, 0x1E, 0x1F, 0x20, 0x1D, 0x1C, 0x1B, 0x00,
- 0x42, 0x43, 0x44, 0x45, 0x48, 0x47, 0x46, 0x06,
- 0x07, 0x08, 0x00, 0x00, 0x2A, 0x00, 0x39, 0x3A,
- 0x3B, 0x3C, 0x3D, 0x40, 0x3F, 0x3E, 0x2D, 0x2C,
- 0x2B, 0x26, 0x00, 0x00, 0x31, 0x32, 0x33, 0x34,
- 0x35, 0x37, 0x36, 0x2e, 0x2f, 0x30, 0x00, 0x00,
- 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+static const int qcode_to_nextkbd_keycode[] = {
+ [Q_KEY_CODE_ESC] = 0x49,
+ [Q_KEY_CODE_1] = 0x4a,
+ [Q_KEY_CODE_2] = 0x4b,
+ [Q_KEY_CODE_3] = 0x4c,
+ [Q_KEY_CODE_4] = 0x4d,
+ [Q_KEY_CODE_5] = 0x50,
+ [Q_KEY_CODE_6] = 0x4f,
+ [Q_KEY_CODE_7] = 0x4e,
+ [Q_KEY_CODE_8] = 0x1e,
+ [Q_KEY_CODE_9] = 0x1f,
+ [Q_KEY_CODE_0] = 0x20,
+ [Q_KEY_CODE_MINUS] = 0x1d,
+ [Q_KEY_CODE_EQUAL] = 0x1c,
+ [Q_KEY_CODE_BACKSPACE] = 0x1b,
+
+ [Q_KEY_CODE_Q] = 0x42,
+ [Q_KEY_CODE_W] = 0x43,
+ [Q_KEY_CODE_E] = 0x44,
+ [Q_KEY_CODE_R] = 0x45,
+ [Q_KEY_CODE_T] = 0x48,
+ [Q_KEY_CODE_Y] = 0x47,
+ [Q_KEY_CODE_U] = 0x46,
+ [Q_KEY_CODE_I] = 0x06,
+ [Q_KEY_CODE_O] = 0x07,
+ [Q_KEY_CODE_P] = 0x08,
+ [Q_KEY_CODE_RET] = 0x2a,
+ [Q_KEY_CODE_A] = 0x39,
+ [Q_KEY_CODE_S] = 0x3a,
+
+ [Q_KEY_CODE_D] = 0x3b,
+ [Q_KEY_CODE_F] = 0x3c,
+ [Q_KEY_CODE_G] = 0x3d,
+ [Q_KEY_CODE_H] = 0x40,
+ [Q_KEY_CODE_J] = 0x3f,
+ [Q_KEY_CODE_K] = 0x3e,
+ [Q_KEY_CODE_L] = 0x2d,
+ [Q_KEY_CODE_SEMICOLON] = 0x2c,
+ [Q_KEY_CODE_APOSTROPHE] = 0x2b,
+ [Q_KEY_CODE_GRAVE_ACCENT] = 0x26,
+ [Q_KEY_CODE_Z] = 0x31,
+ [Q_KEY_CODE_X] = 0x32,
+ [Q_KEY_CODE_C] = 0x33,
+ [Q_KEY_CODE_V] = 0x34,
+
+ [Q_KEY_CODE_B] = 0x35,
+ [Q_KEY_CODE_N] = 0x37,
+ [Q_KEY_CODE_M] = 0x36,
+ [Q_KEY_CODE_COMMA] = 0x2e,
+ [Q_KEY_CODE_DOT] = 0x2f,
+ [Q_KEY_CODE_SLASH] = 0x30,
+
+ [Q_KEY_CODE_SPC] = 0x38,
};
-static void queue_code(void *opaque, int code)
+static void nextkbd_put_keycode(NextKBDState *s, int keycode)
{
- NextKBDState *s = NEXTKBD(opaque);
KBDQueue *q = &s->queue;
- int key = code & KD_KEYMASK;
- int release = code & 0x80;
- static int ext;
-
- if (code == 0xE0) {
- ext = 1;
- }
-
- if (code == 0x2A || code == 0x1D || code == 0x36) {
- if (code == 0x2A) {
- s->shift = KD_LSHIFT;
- } else if (code == 0x36) {
- s->shift = KD_RSHIFT;
- ext = 0;
- } else if (code == 0x1D && !ext) {
- s->shift = KD_LCOMM;
- } else if (code == 0x1D && ext) {
- ext = 0;
- s->shift = KD_RCOMM;
- }
- return;
- } else if (code == (0x2A | 0x80) || code == (0x1D | 0x80) ||
- code == (0x36 | 0x80)) {
- s->shift = 0;
- return;
- }
if (q->count >= KBD_QUEUE_SIZE) {
return;
}
- q->data[q->wptr] = next_keycodes[key] | release;
-
+ q->data[q->wptr] = keycode;
if (++q->wptr == KBD_QUEUE_SIZE) {
q->wptr = 0;
}
@@ -241,6 +242,53 @@ static void queue_code(void *opaque, int code)
/* s->update_irq(s->update_arg, 1); */
}
+static void nextkbd_event(DeviceState *dev, QemuConsole *src, InputEvent *evt)
+{
+ NextKBDState *s = NEXTKBD(dev);
+ int qcode, keycode;
+ bool key_down = evt->u.key.data->down;
+
+ qcode = qemu_input_key_value_to_qcode(evt->u.key.data->key);
+ if (qcode >= ARRAY_SIZE(qcode_to_nextkbd_keycode)) {
+ return;
+ }
+
+ /* Shift key currently has no keycode, so handle separately */
+ if (qcode == Q_KEY_CODE_SHIFT) {
+ if (key_down) {
+ s->shift |= KD_LSHIFT;
+ } else {
+ s->shift &= ~KD_LSHIFT;
+ }
+ }
+
+ if (qcode == Q_KEY_CODE_SHIFT_R) {
+ if (key_down) {
+ s->shift |= KD_RSHIFT;
+ } else {
+ s->shift &= ~KD_RSHIFT;
+ }
+ }
+
+ keycode = qcode_to_nextkbd_keycode[qcode];
+ if (!keycode) {
+ return;
+ }
+
+ /* If key release event, create keyboard break code */
+ if (!key_down) {
+ keycode |= 0x80;
+ }
+
+ nextkbd_put_keycode(s, keycode);
+}
+
+static const QemuInputHandler nextkbd_handler = {
+ .name = "QEMU NeXT Keyboard",
+ .mask = INPUT_EVENT_MASK_KEY,
+ .event = nextkbd_event,
+};
+
static void nextkbd_reset(DeviceState *dev)
{
NextKBDState *nks = NEXTKBD(dev);
@@ -256,7 +304,7 @@ static void nextkbd_realize(DeviceState *dev, Error **errp)
memory_region_init_io(&s->mr, OBJECT(dev), &kbd_ops, s, "next.kbd", 0x1000);
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mr);
- qemu_add_kbd_event_handler(nextkbd_event, s);
+ qemu_input_handler_register(dev, &nextkbd_handler);
}
static const VMStateDescription nextkbd_vmstate = {
@@ -264,14 +312,14 @@ static const VMStateDescription nextkbd_vmstate = {
.unmigratable = 1, /* TODO: Implement this when m68k CPU is migratable */
};
-static void nextkbd_class_init(ObjectClass *oc, void *data)
+static void nextkbd_class_init(ObjectClass *oc, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
dc->vmsd = &nextkbd_vmstate;
dc->realize = nextkbd_realize;
- dc->reset = nextkbd_reset;
+ device_class_set_legacy_reset(dc, nextkbd_reset);
}
static const TypeInfo nextkbd_info = {
diff --git a/hw/m68k/q800-glue.c b/hw/m68k/q800-glue.c
index e2ae7c3..36de67c 100644
--- a/hw/m68k/q800-glue.c
+++ b/hw/m68k/q800-glue.c
@@ -203,9 +203,8 @@ static const VMStateDescription vmstate_glue = {
* this cpu link property and could instead provide outbound IRQ lines
* that the board could wire up to the CPU.
*/
-static Property glue_properties[] = {
+static const Property glue_properties[] = {
DEFINE_PROP_LINK("cpu", GLUEState, cpu, TYPE_M68K_CPU, M68kCPU *),
- DEFINE_PROP_END_OF_LIST(),
};
static void glue_finalize(Object *obj)
@@ -229,7 +228,7 @@ static void glue_init(Object *obj)
s->nmi_release = timer_new_ms(QEMU_CLOCK_VIRTUAL, glue_nmi_release, s);
}
-static void glue_class_init(ObjectClass *klass, void *data)
+static void glue_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
ResettableClass *rc = RESETTABLE_CLASS(klass);
@@ -249,7 +248,7 @@ static const TypeInfo glue_info_types[] = {
.instance_init = glue_init,
.instance_finalize = glue_finalize,
.class_init = glue_class_init,
- .interfaces = (InterfaceInfo[]) {
+ .interfaces = (const InterfaceInfo[]) {
{ TYPE_NMI },
{ }
},
diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c
index fa7683b..793b23f 100644
--- a/hw/m68k/q800.c
+++ b/hw/m68k/q800.c
@@ -24,7 +24,8 @@
#include "qemu/units.h"
#include "qemu/datadir.h"
#include "qemu/guest-random.h"
-#include "sysemu/sysemu.h"
+#include "exec/target_page.h"
+#include "system/system.h"
#include "cpu.h"
#include "hw/boards.h"
#include "hw/or-irq.h"
@@ -51,9 +52,9 @@
#include "net/util.h"
#include "qapi/error.h"
#include "qemu/error-report.h"
-#include "sysemu/qtest.h"
-#include "sysemu/runstate.h"
-#include "sysemu/reset.h"
+#include "system/qtest.h"
+#include "system/runstate.h"
+#include "system/reset.h"
#include "migration/vmstate.h"
#define MACROM_ADDR 0x40800000
@@ -210,7 +211,6 @@ static uint64_t machine_id_read(void *opaque, hwaddr addr, unsigned size)
static void machine_id_write(void *opaque, hwaddr addr, uint64_t val,
unsigned size)
{
- return;
}
static const MemoryRegionOps machine_id_ops = {
@@ -231,7 +231,6 @@ static uint64_t ramio_read(void *opaque, hwaddr addr, unsigned size)
static void ramio_write(void *opaque, hwaddr addr, uint64_t val,
unsigned size)
{
- return;
}
static const MemoryRegionOps ramio_ops = {
@@ -585,7 +584,7 @@ static void q800_machine_init(MachineState *machine)
}
kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
- &elf_entry, NULL, &high, NULL, 1,
+ &elf_entry, NULL, &high, NULL, ELFDATA2MSB,
EM_68K, 0, 0);
if (kernel_size < 0) {
error_report("could not load kernel '%s'", kernel_filename);
@@ -684,9 +683,9 @@ static void q800_machine_init(MachineState *machine)
ptr = rom_ptr(MACROM_ADDR, bios_size);
assert(ptr != NULL);
- stl_phys(cs->as, 0, ldl_p(ptr)); /* reset initial SP */
+ stl_phys(cs->as, 0, ldl_be_p(ptr)); /* reset initial SP */
stl_phys(cs->as, 4,
- MACROM_ADDR + ldl_p(ptr + 4)); /* reset initial PC */
+ MACROM_ADDR + ldl_be_p(ptr + 4)); /* reset initial PC */
}
}
}
@@ -728,7 +727,7 @@ static GlobalProperty hw_compat_q800[] = {
};
static const size_t hw_compat_q800_len = G_N_ELEMENTS(hw_compat_q800);
-static void q800_machine_class_init(ObjectClass *oc, void *data)
+static void q800_machine_class_init(ObjectClass *oc, const void *data)
{
static const char * const valid_cpu_types[] = {
M68K_CPU_TYPE_NAME("m68040"),
diff --git a/hw/m68k/virt.c b/hw/m68k/virt.c
index 09bc9bd..875fd00 100644
--- a/hw/m68k/virt.c
+++ b/hw/m68k/virt.c
@@ -10,7 +10,8 @@
#include "qemu/osdep.h"
#include "qemu/units.h"
#include "qemu/guest-random.h"
-#include "sysemu/sysemu.h"
+#include "exec/target_page.h"
+#include "system/system.h"
#include "cpu.h"
#include "hw/boards.h"
#include "hw/qdev-properties.h"
@@ -24,9 +25,9 @@
#include "net/net.h"
#include "qapi/error.h"
#include "qemu/error-report.h"
-#include "sysemu/qtest.h"
-#include "sysemu/runstate.h"
-#include "sysemu/reset.h"
+#include "system/qtest.h"
+#include "system/runstate.h"
+#include "system/reset.h"
#include "hw/intc/m68k_irqc.h"
#include "hw/misc/virt_ctrl.h"
@@ -228,7 +229,7 @@ static void virt_init(MachineState *machine)
}
kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
- &elf_entry, NULL, &high, NULL, 1,
+ &elf_entry, NULL, &high, NULL, ELFDATA2MSB,
EM_68K, 0, 0);
if (kernel_size < 0) {
error_report("could not load kernel '%s'", kernel_filename);
@@ -309,7 +310,7 @@ static void virt_init(MachineState *machine)
}
}
-static void virt_machine_class_init(ObjectClass *oc, void *data)
+static void virt_machine_class_init(ObjectClass *oc, const void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
mc->desc = "QEMU M68K Virtual Machine";
@@ -335,99 +336,129 @@ static void virt_machine_register_types(void)
type_init(virt_machine_register_types)
-#define DEFINE_VIRT_MACHINE(major, minor, latest) \
- static void virt_##major##_##minor##_class_init(ObjectClass *oc, \
- void *data) \
+#define DEFINE_VIRT_MACHINE_IMPL(latest, ...) \
+ static void MACHINE_VER_SYM(class_init, virt, __VA_ARGS__)( \
+ ObjectClass *oc, \
+ const void *data) \
{ \
MachineClass *mc = MACHINE_CLASS(oc); \
- virt_machine_##major##_##minor##_options(mc); \
- mc->desc = "QEMU " # major "." # minor " M68K Virtual Machine"; \
+ MACHINE_VER_SYM(options, virt, __VA_ARGS__)(mc); \
+ mc->desc = "QEMU " MACHINE_VER_STR(__VA_ARGS__) " M68K Virtual Machine"; \
+ MACHINE_VER_DEPRECATION(__VA_ARGS__); \
if (latest) { \
mc->alias = "virt"; \
} \
} \
- static const TypeInfo machvirt_##major##_##minor##_info = { \
- .name = MACHINE_TYPE_NAME("virt-" # major "." # minor), \
+ static const TypeInfo MACHINE_VER_SYM(info, virt, __VA_ARGS__) = \
+ { \
+ .name = MACHINE_VER_TYPE_NAME("virt", __VA_ARGS__), \
.parent = MACHINE_TYPE_NAME("virt"), \
- .class_init = virt_##major##_##minor##_class_init, \
+ .class_init = MACHINE_VER_SYM(class_init, virt, __VA_ARGS__), \
}; \
- static void machvirt_machine_##major##_##minor##_init(void) \
+ static void MACHINE_VER_SYM(register, virt, __VA_ARGS__)(void) \
{ \
- type_register_static(&machvirt_##major##_##minor##_info); \
+ MACHINE_VER_DELETION(__VA_ARGS__); \
+ type_register_static(&MACHINE_VER_SYM(info, virt, __VA_ARGS__)); \
} \
- type_init(machvirt_machine_##major##_##minor##_init);
+ type_init(MACHINE_VER_SYM(register, virt, __VA_ARGS__));
+
+#define DEFINE_VIRT_MACHINE_AS_LATEST(major, minor) \
+ DEFINE_VIRT_MACHINE_IMPL(true, major, minor)
+#define DEFINE_VIRT_MACHINE(major, minor) \
+ DEFINE_VIRT_MACHINE_IMPL(false, major, minor)
+
+static void virt_machine_10_1_options(MachineClass *mc)
+{
+}
+DEFINE_VIRT_MACHINE_AS_LATEST(10, 1)
+
+static void virt_machine_10_0_options(MachineClass *mc)
+{
+ virt_machine_10_1_options(mc);
+ compat_props_add(mc->compat_props, hw_compat_10_0, hw_compat_10_0_len);
+}
+DEFINE_VIRT_MACHINE(10, 0)
+
+static void virt_machine_9_2_options(MachineClass *mc)
+{
+ virt_machine_10_0_options(mc);
+ compat_props_add(mc->compat_props, hw_compat_9_2, hw_compat_9_2_len);
+}
+DEFINE_VIRT_MACHINE(9, 2)
static void virt_machine_9_1_options(MachineClass *mc)
{
+ virt_machine_9_2_options(mc);
+ compat_props_add(mc->compat_props, hw_compat_9_1, hw_compat_9_1_len);
}
-DEFINE_VIRT_MACHINE(9, 1, true)
+DEFINE_VIRT_MACHINE(9, 1)
static void virt_machine_9_0_options(MachineClass *mc)
{
virt_machine_9_1_options(mc);
compat_props_add(mc->compat_props, hw_compat_9_0, hw_compat_9_0_len);
}
-DEFINE_VIRT_MACHINE(9, 0, false)
+DEFINE_VIRT_MACHINE(9, 0)
static void virt_machine_8_2_options(MachineClass *mc)
{
virt_machine_9_0_options(mc);
compat_props_add(mc->compat_props, hw_compat_8_2, hw_compat_8_2_len);
}
-DEFINE_VIRT_MACHINE(8, 2, false)
+DEFINE_VIRT_MACHINE(8, 2)
static void virt_machine_8_1_options(MachineClass *mc)
{
virt_machine_8_2_options(mc);
compat_props_add(mc->compat_props, hw_compat_8_1, hw_compat_8_1_len);
}
-DEFINE_VIRT_MACHINE(8, 1, false)
+DEFINE_VIRT_MACHINE(8, 1)
static void virt_machine_8_0_options(MachineClass *mc)
{
virt_machine_8_1_options(mc);
compat_props_add(mc->compat_props, hw_compat_8_0, hw_compat_8_0_len);
}
-DEFINE_VIRT_MACHINE(8, 0, false)
+DEFINE_VIRT_MACHINE(8, 0)
static void virt_machine_7_2_options(MachineClass *mc)
{
virt_machine_8_0_options(mc);
compat_props_add(mc->compat_props, hw_compat_7_2, hw_compat_7_2_len);
}
-DEFINE_VIRT_MACHINE(7, 2, false)
+DEFINE_VIRT_MACHINE(7, 2)
static void virt_machine_7_1_options(MachineClass *mc)
{
virt_machine_7_2_options(mc);
compat_props_add(mc->compat_props, hw_compat_7_1, hw_compat_7_1_len);
}
-DEFINE_VIRT_MACHINE(7, 1, false)
+DEFINE_VIRT_MACHINE(7, 1)
static void virt_machine_7_0_options(MachineClass *mc)
{
virt_machine_7_1_options(mc);
compat_props_add(mc->compat_props, hw_compat_7_0, hw_compat_7_0_len);
}
-DEFINE_VIRT_MACHINE(7, 0, false)
+DEFINE_VIRT_MACHINE(7, 0)
static void virt_machine_6_2_options(MachineClass *mc)
{
virt_machine_7_0_options(mc);
compat_props_add(mc->compat_props, hw_compat_6_2, hw_compat_6_2_len);
}
-DEFINE_VIRT_MACHINE(6, 2, false)
+DEFINE_VIRT_MACHINE(6, 2)
static void virt_machine_6_1_options(MachineClass *mc)
{
virt_machine_6_2_options(mc);
compat_props_add(mc->compat_props, hw_compat_6_1, hw_compat_6_1_len);
}
-DEFINE_VIRT_MACHINE(6, 1, false)
+DEFINE_VIRT_MACHINE(6, 1)
static void virt_machine_6_0_options(MachineClass *mc)
{
virt_machine_6_1_options(mc);
compat_props_add(mc->compat_props, hw_compat_6_0, hw_compat_6_0_len);
}
-DEFINE_VIRT_MACHINE(6, 0, false)
+DEFINE_VIRT_MACHINE(6, 0)