m68k: fix CACR valid bits
q800: add a fake mac rom reset (used by linux) fix and improve PRAM emulation -----BEGIN PGP SIGNATURE----- iQJGBAABCAAwFiEEzS913cjjpNwuT1Fz8ww4vT8vvjwFAl4Uht4SHGxhdXJlbnRA dml2aWVyLmV1AAoJEPMMOL0/L748ProQAI55Kc5Nvg8pgn1t/jg10d2/xlM2HG6c nEKb+i6ElHYjMhcGS4gUBCTlr09k47GkQdzKP8NU7K6rX9cPvH/qq+Y5sZ8zIcvU dl67cya2HOTBySaVMr9cYEvB0q3AyL8Kt146ntmjBEWAoZWHxehI8TALMrBk3KF0 +5vrAi6xL9aalnawH+iG5kBoJgLSWNWbQVM1HENDnzbbIZDHeGDbOUlVZr6suH35 mclZ2tgaXWl5wTfeNTDuei3DDenYOxus7bM4S9ruKvaybVK2XguiXjH+vmdehiQO CPKz3z87Ow9eU55VqXfnlp/6g63Ccr5LD6wEkL8RyQ+WBHXkDyQRO23dzSC+hS47 XZ/b2ZmRhWZ0Mi7tZpWyJliuN3mRQ07FEUQ9Irokq+hrBIQqDtFiOOAVNvOJU3op QN/ltfEmjrKblA/cqgXl4wknPruboSkdhiea57XJ1IfOJfSjo7onsFEH4LP6XDxB zw1yndCSKjX/V7+j4PB+1sXgXMLlHOjGWh5E/9yMOSzMaJU5Pjqv27sFs24htzBu ZrM6+iox8MCH1dyciV1m5AbtlqpCI56JK4wNFzR9PQvubMUCttqzLCwm0SG3RSKk Wa8CNyX5Xkg7tH1jTWqMriWCHoHrnFAIu80KpayMVaZaX41VVvIMWpzSOj7MARyY v7MNz2OOncFR =Wld2 -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/vivier/tags/q800-for-5.0-pull-request' into staging m68k: fix CACR valid bits q800: add a fake mac rom reset (used by linux) fix and improve PRAM emulation # gpg: Signature made Tue 07 Jan 2020 13:25:50 GMT # gpg: using RSA key CD2F75DDC8E3A4DC2E4F5173F30C38BD3F2FBE3C # gpg: issuer "laurent@vivier.eu" # gpg: Good signature from "Laurent Vivier <lvivier@redhat.com>" [full] # gpg: aka "Laurent Vivier <laurent@vivier.eu>" [full] # gpg: aka "Laurent Vivier (Red Hat) <lvivier@redhat.com>" [full] # Primary key fingerprint: CD2F 75DD C8E3 A4DC 2E4F 5173 F30C 38BD 3F2F BE3C * remotes/vivier/tags/q800-for-5.0-pull-request: target/m68k: only change valid bits in CACR q800: implement mac rom reset function for BIOS-less mode q800: add a block backend to the PRAM q800: fix mac_via RTC PRAM commands Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
035eed4c0d
@ -47,7 +47,7 @@
|
||||
#include "sysemu/runstate.h"
|
||||
#include "sysemu/reset.h"
|
||||
|
||||
#define MACROM_ADDR 0x40000000
|
||||
#define MACROM_ADDR 0x40800000
|
||||
#define MACROM_SIZE 0x00100000
|
||||
|
||||
#define MACROM_FILENAME "MacROM.bin"
|
||||
@ -128,6 +128,27 @@ static void main_cpu_reset(void *opaque)
|
||||
cpu->env.pc = ldl_phys(cs->as, 4);
|
||||
}
|
||||
|
||||
static uint8_t fake_mac_rom[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
/* offset: 0xa - mac_reset */
|
||||
|
||||
/* via2[vDirB] |= VIA2B_vPower */
|
||||
0x20, 0x7C, 0x50, 0xF0, 0x24, 0x00, /* moveal VIA2_BASE+vDirB,%a0 */
|
||||
0x10, 0x10, /* moveb %a0@,%d0 */
|
||||
0x00, 0x00, 0x00, 0x04, /* orib #4,%d0 */
|
||||
0x10, 0x80, /* moveb %d0,%a0@ */
|
||||
|
||||
/* via2[vBufB] &= ~VIA2B_vPower */
|
||||
0x20, 0x7C, 0x50, 0xF0, 0x20, 0x00, /* moveal VIA2_BASE+vBufB,%a0 */
|
||||
0x10, 0x10, /* moveb %a0@,%d0 */
|
||||
0x02, 0x00, 0xFF, 0xFB, /* andib #-5,%d0 */
|
||||
0x10, 0x80, /* moveb %d0,%a0@ */
|
||||
|
||||
/* while (true) ; */
|
||||
0x60, 0xFE /* bras [self] */
|
||||
};
|
||||
|
||||
static void q800_init(MachineState *machine)
|
||||
{
|
||||
M68kCPU *cpu = NULL;
|
||||
@ -158,6 +179,7 @@ static void q800_init(MachineState *machine)
|
||||
NubusBus *nubus;
|
||||
GLUEState *irq;
|
||||
qemu_irq *pic;
|
||||
DriveInfo *dinfo;
|
||||
|
||||
linux_boot = (kernel_filename != NULL);
|
||||
|
||||
@ -200,6 +222,11 @@ static void q800_init(MachineState *machine)
|
||||
/* VIA */
|
||||
|
||||
via_dev = qdev_create(NULL, TYPE_MAC_VIA);
|
||||
dinfo = drive_get(IF_MTD, 0, 0);
|
||||
if (dinfo) {
|
||||
qdev_prop_set_drive(via_dev, "drive", blk_by_legacy_dinfo(dinfo),
|
||||
&error_abort);
|
||||
}
|
||||
qdev_init_nofail(via_dev);
|
||||
sysbus = SYS_BUS_DEVICE(via_dev);
|
||||
sysbus_mmio_map(sysbus, 0, VIA_BASE);
|
||||
@ -340,6 +367,12 @@ static void q800_init(MachineState *machine)
|
||||
(graphic_width * graphic_depth + 7) / 8);
|
||||
BOOTINFO1(cs->as, parameters_base, BI_MAC_SCCBASE, SCC_BASE);
|
||||
|
||||
rom = g_malloc(sizeof(*rom));
|
||||
memory_region_init_ram_ptr(rom, NULL, "m68k_fake_mac.rom",
|
||||
sizeof(fake_mac_rom), fake_mac_rom);
|
||||
memory_region_set_readonly(rom, true);
|
||||
memory_region_add_subregion(get_system_memory(), MACROM_ADDR, rom);
|
||||
|
||||
if (kernel_cmdline) {
|
||||
BOOTINFOSTR(cs->as, parameters_base, BI_COMMAND_LINE,
|
||||
kernel_cmdline);
|
||||
|
@ -27,7 +27,9 @@
|
||||
#include "sysemu/runstate.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/cutils.h"
|
||||
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
#include "trace.h"
|
||||
|
||||
/*
|
||||
* VIAs: There are two in every machine,
|
||||
@ -278,6 +280,21 @@
|
||||
/* VIA returns time offset from Jan 1, 1904, not 1970 */
|
||||
#define RTC_OFFSET 2082844800
|
||||
|
||||
enum {
|
||||
REG_0,
|
||||
REG_1,
|
||||
REG_2,
|
||||
REG_3,
|
||||
REG_TEST,
|
||||
REG_WPROTECT,
|
||||
REG_PRAM_ADDR,
|
||||
REG_PRAM_ADDR_LAST = REG_PRAM_ADDR + 19,
|
||||
REG_PRAM_SECT,
|
||||
REG_PRAM_SECT_LAST = REG_PRAM_SECT + 7,
|
||||
REG_INVALID,
|
||||
REG_EMPTY = 0xff,
|
||||
};
|
||||
|
||||
static void via1_VBL_update(MOS6522Q800VIA1State *v1s)
|
||||
{
|
||||
MOS6522State *s = MOS6522(v1s);
|
||||
@ -360,10 +377,71 @@ static void via2_irq_request(void *opaque, int irq, int level)
|
||||
mdc->update_irq(s);
|
||||
}
|
||||
|
||||
|
||||
static void pram_update(MacVIAState *m)
|
||||
{
|
||||
if (m->blk) {
|
||||
blk_pwrite(m->blk, 0, m->mos6522_via1.PRAM,
|
||||
sizeof(m->mos6522_via1.PRAM), 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* RTC Commands
|
||||
*
|
||||
* Command byte Register addressed by the command
|
||||
*
|
||||
* z0000001 Seconds register 0 (lowest-order byte)
|
||||
* z0000101 Seconds register 1
|
||||
* z0001001 Seconds register 2
|
||||
* z0001101 Seconds register 3 (highest-order byte)
|
||||
* 00110001 Test register (write-only)
|
||||
* 00110101 Write-Protect Register (write-only)
|
||||
* z010aa01 RAM address 100aa ($10-$13) (first 20 bytes only)
|
||||
* z1aaaa01 RAM address 0aaaa ($00-$0F) (first 20 bytes only)
|
||||
* z0111aaa Extended memory designator and sector number
|
||||
*
|
||||
* For a read request, z=1, for a write z=0
|
||||
* The letter a indicates bits whose value depend on what parameter
|
||||
* RAM byte you want to address
|
||||
*/
|
||||
static int via1_rtc_compact_cmd(uint8_t value)
|
||||
{
|
||||
uint8_t read = value & 0x80;
|
||||
|
||||
value &= 0x7f;
|
||||
|
||||
/* the last 2 bits of a command byte must always be 0b01 ... */
|
||||
if ((value & 0x78) == 0x38) {
|
||||
/* except for the extended memory designator */
|
||||
return read | (REG_PRAM_SECT + (value & 0x07));
|
||||
}
|
||||
if ((value & 0x03) == 0x01) {
|
||||
value >>= 2;
|
||||
if ((value & 0x1c) == 0) {
|
||||
/* seconds registers */
|
||||
return read | (REG_0 + (value & 0x03));
|
||||
} else if ((value == 0x0c) && !read) {
|
||||
return REG_TEST;
|
||||
} else if ((value == 0x0d) && !read) {
|
||||
return REG_WPROTECT;
|
||||
} else if ((value & 0x1c) == 0x08) {
|
||||
/* RAM address 0x10 to 0x13 */
|
||||
return read | (REG_PRAM_ADDR + 0x10 + (value & 0x03));
|
||||
} else if ((value & 0x43) == 0x41) {
|
||||
/* RAM address 0x00 to 0x0f */
|
||||
return read | (REG_PRAM_ADDR + (value & 0x0f));
|
||||
}
|
||||
}
|
||||
return REG_INVALID;
|
||||
}
|
||||
|
||||
static void via1_rtc_update(MacVIAState *m)
|
||||
{
|
||||
MOS6522Q800VIA1State *v1s = &m->mos6522_via1;
|
||||
MOS6522State *s = MOS6522(v1s);
|
||||
int cmd, sector, addr;
|
||||
uint32_t time;
|
||||
|
||||
if (s->b & VIA1B_vRTCEnb) {
|
||||
return;
|
||||
@ -376,7 +454,9 @@ static void via1_rtc_update(MacVIAState *m)
|
||||
m->data_out |= s->b & VIA1B_vRTCData;
|
||||
m->data_out_cnt++;
|
||||
}
|
||||
trace_via1_rtc_update_data_out(m->data_out_cnt, m->data_out);
|
||||
} else {
|
||||
trace_via1_rtc_update_data_in(m->data_in_cnt, m->data_in);
|
||||
/* receive bits from the RTC */
|
||||
if ((v1s->last_b & VIA1B_vRTCClk) &&
|
||||
!(s->b & VIA1B_vRTCClk) &&
|
||||
@ -386,96 +466,134 @@ static void via1_rtc_update(MacVIAState *m)
|
||||
m->data_in <<= 1;
|
||||
m->data_in_cnt--;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (m->data_out_cnt == 8) {
|
||||
m->data_out_cnt = 0;
|
||||
if (m->data_out_cnt != 8) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m->cmd == 0) {
|
||||
if (m->data_out & 0x80) {
|
||||
/* this is a read command */
|
||||
uint32_t time = m->tick_offset +
|
||||
(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) /
|
||||
NANOSECONDS_PER_SECOND);
|
||||
if (m->data_out == 0x81) { /* seconds register 0 */
|
||||
m->data_in = time & 0xff;
|
||||
m->data_in_cnt = 8;
|
||||
} else if (m->data_out == 0x85) { /* seconds register 1 */
|
||||
m->data_in = (time >> 8) & 0xff;
|
||||
m->data_in_cnt = 8;
|
||||
} else if (m->data_out == 0x89) { /* seconds register 2 */
|
||||
m->data_in = (time >> 16) & 0xff;
|
||||
m->data_in_cnt = 8;
|
||||
} else if (m->data_out == 0x8d) { /* seconds register 3 */
|
||||
m->data_in = (time >> 24) & 0xff;
|
||||
m->data_in_cnt = 8;
|
||||
} else if ((m->data_out & 0xf3) == 0xa1) {
|
||||
/* PRAM address 0x10 -> 0x13 */
|
||||
int addr = (m->data_out >> 2) & 0x03;
|
||||
m->data_in = v1s->PRAM[addr];
|
||||
m->data_in_cnt = 8;
|
||||
} else if ((m->data_out & 0xf3) == 0xa1) {
|
||||
/* PRAM address 0x00 -> 0x0f */
|
||||
int addr = (m->data_out >> 2) & 0x0f;
|
||||
m->data_in = v1s->PRAM[addr];
|
||||
m->data_in_cnt = 8;
|
||||
} else if ((m->data_out & 0xf8) == 0xb8) {
|
||||
/* extended memory designator and sector number */
|
||||
m->cmd = m->data_out;
|
||||
}
|
||||
} else {
|
||||
/* this is a write command */
|
||||
m->cmd = m->data_out;
|
||||
}
|
||||
} else {
|
||||
if (m->cmd & 0x80) {
|
||||
if ((m->cmd & 0xf8) == 0xb8) {
|
||||
/* extended memory designator and sector number */
|
||||
int sector = m->cmd & 0x07;
|
||||
int addr = (m->data_out >> 2) & 0x1f;
|
||||
m->data_out_cnt = 0;
|
||||
|
||||
m->data_in = v1s->PRAM[sector * 8 + addr];
|
||||
m->data_in_cnt = 8;
|
||||
}
|
||||
} else if (!m->wprotect) {
|
||||
/* this is a write command */
|
||||
if (m->alt != 0) {
|
||||
/* extended memory designator and sector number */
|
||||
int sector = m->cmd & 0x07;
|
||||
int addr = (m->alt >> 2) & 0x1f;
|
||||
trace_via1_rtc_internal_status(m->cmd, m->alt, m->data_out);
|
||||
/* first byte: it's a command */
|
||||
if (m->cmd == REG_EMPTY) {
|
||||
|
||||
v1s->PRAM[sector * 8 + addr] = m->data_out;
|
||||
cmd = via1_rtc_compact_cmd(m->data_out);
|
||||
trace_via1_rtc_internal_cmd(cmd);
|
||||
|
||||
m->alt = 0;
|
||||
} else if (m->cmd == 0x01) { /* seconds register 0 */
|
||||
/* FIXME */
|
||||
} else if (m->cmd == 0x05) { /* seconds register 1 */
|
||||
/* FIXME */
|
||||
} else if (m->cmd == 0x09) { /* seconds register 2 */
|
||||
/* FIXME */
|
||||
} else if (m->cmd == 0x0d) { /* seconds register 3 */
|
||||
/* FIXME */
|
||||
} else if (m->cmd == 0x31) {
|
||||
/* Test Register */
|
||||
} else if (m->cmd == 0x35) {
|
||||
/* Write Protect register */
|
||||
m->wprotect = m->data_out & 1;
|
||||
} else if ((m->cmd & 0xf3) == 0xa1) {
|
||||
/* PRAM address 0x10 -> 0x13 */
|
||||
int addr = (m->cmd >> 2) & 0x03;
|
||||
v1s->PRAM[addr] = m->data_out;
|
||||
} else if ((m->cmd & 0xf3) == 0xa1) {
|
||||
/* PRAM address 0x00 -> 0x0f */
|
||||
int addr = (m->cmd >> 2) & 0x0f;
|
||||
v1s->PRAM[addr] = m->data_out;
|
||||
} else if ((m->cmd & 0xf8) == 0xb8) {
|
||||
/* extended memory designator and sector number */
|
||||
m->alt = m->cmd;
|
||||
}
|
||||
}
|
||||
if (cmd == REG_INVALID) {
|
||||
trace_via1_rtc_cmd_invalid(m->data_out);
|
||||
return;
|
||||
}
|
||||
m->data_out = 0;
|
||||
|
||||
if (cmd & 0x80) { /* this is a read command */
|
||||
switch (cmd & 0x7f) {
|
||||
case REG_0...REG_3: /* seconds registers */
|
||||
/*
|
||||
* register 0 is lowest-order byte
|
||||
* register 3 is highest-order byte
|
||||
*/
|
||||
|
||||
time = m->tick_offset + (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)
|
||||
/ NANOSECONDS_PER_SECOND);
|
||||
trace_via1_rtc_internal_time(time);
|
||||
m->data_in = (time >> ((cmd & 0x03) << 3)) & 0xff;
|
||||
m->data_in_cnt = 8;
|
||||
trace_via1_rtc_cmd_seconds_read((cmd & 0x7f) - REG_0,
|
||||
m->data_in);
|
||||
break;
|
||||
case REG_PRAM_ADDR...REG_PRAM_ADDR_LAST:
|
||||
/* PRAM address 0x00 -> 0x13 */
|
||||
m->data_in = v1s->PRAM[(cmd & 0x7f) - REG_PRAM_ADDR];
|
||||
m->data_in_cnt = 8;
|
||||
trace_via1_rtc_cmd_pram_read((cmd & 0x7f) - REG_PRAM_ADDR,
|
||||
m->data_in);
|
||||
break;
|
||||
case REG_PRAM_SECT...REG_PRAM_SECT_LAST:
|
||||
/*
|
||||
* extended memory designator and sector number
|
||||
* the only two-byte read command
|
||||
*/
|
||||
trace_via1_rtc_internal_set_cmd(cmd);
|
||||
m->cmd = cmd;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* this is a write command, needs a parameter */
|
||||
if (cmd == REG_WPROTECT || !m->wprotect) {
|
||||
trace_via1_rtc_internal_set_cmd(cmd);
|
||||
m->cmd = cmd;
|
||||
} else {
|
||||
trace_via1_rtc_internal_ignore_cmd(cmd);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* second byte: it's a parameter */
|
||||
if (m->alt == REG_EMPTY) {
|
||||
switch (m->cmd & 0x7f) {
|
||||
case REG_0...REG_3: /* seconds register */
|
||||
/* FIXME */
|
||||
trace_via1_rtc_cmd_seconds_write(m->cmd - REG_0, m->data_out);
|
||||
m->cmd = REG_EMPTY;
|
||||
break;
|
||||
case REG_TEST:
|
||||
/* device control: nothing to do */
|
||||
trace_via1_rtc_cmd_test_write(m->data_out);
|
||||
m->cmd = REG_EMPTY;
|
||||
break;
|
||||
case REG_WPROTECT:
|
||||
/* Write Protect register */
|
||||
trace_via1_rtc_cmd_wprotect_write(m->data_out);
|
||||
m->wprotect = !!(m->data_out & 0x80);
|
||||
m->cmd = REG_EMPTY;
|
||||
break;
|
||||
case REG_PRAM_ADDR...REG_PRAM_ADDR_LAST:
|
||||
/* PRAM address 0x00 -> 0x13 */
|
||||
trace_via1_rtc_cmd_pram_write(m->cmd - REG_PRAM_ADDR, m->data_out);
|
||||
v1s->PRAM[m->cmd - REG_PRAM_ADDR] = m->data_out;
|
||||
pram_update(m);
|
||||
m->cmd = REG_EMPTY;
|
||||
break;
|
||||
case REG_PRAM_SECT...REG_PRAM_SECT_LAST:
|
||||
addr = (m->data_out >> 2) & 0x1f;
|
||||
sector = (m->cmd & 0x7f) - REG_PRAM_SECT;
|
||||
if (m->cmd & 0x80) {
|
||||
/* it's a read */
|
||||
m->data_in = v1s->PRAM[sector * 32 + addr];
|
||||
m->data_in_cnt = 8;
|
||||
trace_via1_rtc_cmd_pram_sect_read(sector, addr,
|
||||
sector * 32 + addr,
|
||||
m->data_in);
|
||||
m->cmd = REG_EMPTY;
|
||||
} else {
|
||||
/* it's a write, we need one more parameter */
|
||||
trace_via1_rtc_internal_set_alt(addr, sector, addr);
|
||||
m->alt = addr;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* third byte: it's the data of a REG_PRAM_SECT write */
|
||||
g_assert(REG_PRAM_SECT <= m->cmd && m->cmd <= REG_PRAM_SECT_LAST);
|
||||
sector = m->cmd - REG_PRAM_SECT;
|
||||
v1s->PRAM[sector * 32 + m->alt] = m->data_out;
|
||||
pram_update(m);
|
||||
trace_via1_rtc_cmd_pram_sect_write(sector, m->alt, sector * 32 + m->alt,
|
||||
m->data_out);
|
||||
m->alt = REG_EMPTY;
|
||||
m->cmd = REG_EMPTY;
|
||||
}
|
||||
|
||||
static int adb_via_poll(MacVIAState *s, int state, uint8_t *data)
|
||||
@ -742,6 +860,9 @@ static void mac_via_reset(DeviceState *dev)
|
||||
v1s->next_VBL = 0;
|
||||
timer_del(v1s->one_second_timer);
|
||||
v1s->next_second = 0;
|
||||
|
||||
m->cmd = REG_EMPTY;
|
||||
m->alt = REG_EMPTY;
|
||||
}
|
||||
|
||||
static void mac_via_realize(DeviceState *dev, Error **errp)
|
||||
@ -749,6 +870,7 @@ static void mac_via_realize(DeviceState *dev, Error **errp)
|
||||
MacVIAState *m = MAC_VIA(dev);
|
||||
MOS6522State *ms;
|
||||
struct tm tm;
|
||||
int ret;
|
||||
|
||||
/* Init VIAs 1 and 2 */
|
||||
sysbus_init_child_obj(OBJECT(dev), "via1", &m->mos6522_via1,
|
||||
@ -782,6 +904,28 @@ static void mac_via_realize(DeviceState *dev, Error **errp)
|
||||
m->adb_poll_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, via_adb_poll, m);
|
||||
m->adb_data_ready = qdev_get_gpio_in_named(dev, "via1-irq",
|
||||
VIA1_IRQ_ADB_READY_BIT);
|
||||
|
||||
if (m->blk) {
|
||||
int64_t len = blk_getlength(m->blk);
|
||||
if (len < 0) {
|
||||
error_setg_errno(errp, -len,
|
||||
"could not get length of backing image");
|
||||
return;
|
||||
}
|
||||
ret = blk_set_perm(m->blk,
|
||||
BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE,
|
||||
BLK_PERM_ALL, errp);
|
||||
if (ret < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
len = blk_pread(m->blk, 0, m->mos6522_via1.PRAM,
|
||||
sizeof(m->mos6522_via1.PRAM));
|
||||
if (len != sizeof(m->mos6522_via1.PRAM)) {
|
||||
error_setg(errp, "can't read PRAM contents");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void mac_via_init(Object *obj)
|
||||
@ -806,10 +950,33 @@ static void mac_via_init(Object *obj)
|
||||
TYPE_ADB_BUS, DEVICE(obj), "adb.0");
|
||||
}
|
||||
|
||||
static void postload_update_cb(void *opaque, int running, RunState state)
|
||||
{
|
||||
MacVIAState *m = MAC_VIA(opaque);
|
||||
|
||||
qemu_del_vm_change_state_handler(m->vmstate);
|
||||
m->vmstate = NULL;
|
||||
|
||||
pram_update(m);
|
||||
}
|
||||
|
||||
static int mac_via_post_load(void *opaque, int version_id)
|
||||
{
|
||||
MacVIAState *m = MAC_VIA(opaque);
|
||||
|
||||
if (m->blk) {
|
||||
m->vmstate = qemu_add_vm_change_state_handler(postload_update_cb,
|
||||
m);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_mac_via = {
|
||||
.name = "mac-via",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.post_load = mac_via_post_load,
|
||||
.fields = (VMStateField[]) {
|
||||
/* VIAs */
|
||||
VMSTATE_STRUCT(mos6522_via1.parent_obj, MacVIAState, 0, vmstate_mos6522,
|
||||
@ -842,6 +1009,11 @@ static const VMStateDescription vmstate_mac_via = {
|
||||
}
|
||||
};
|
||||
|
||||
static Property mac_via_properties[] = {
|
||||
DEFINE_PROP_DRIVE("drive", MacVIAState, blk),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void mac_via_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
@ -849,6 +1021,7 @@ static void mac_via_class_init(ObjectClass *oc, void *data)
|
||||
dc->realize = mac_via_realize;
|
||||
dc->reset = mac_via_reset;
|
||||
dc->vmsd = &vmstate_mac_via;
|
||||
dc->props = mac_via_properties;
|
||||
}
|
||||
|
||||
static TypeInfo mac_via_info = {
|
||||
|
@ -149,3 +149,22 @@ bcm2835_mbox_write(unsigned int size, uint64_t addr, uint64_t value) "mbox write
|
||||
bcm2835_mbox_read(unsigned int size, uint64_t addr, uint64_t value) "mbox read sz:%u addr:0x%"PRIx64" data:0x%"PRIx64
|
||||
bcm2835_mbox_irq(unsigned level) "mbox irq:ARM level:%u"
|
||||
bcm2835_mbox_property(uint32_t tag, uint32_t bufsize, size_t resplen) "mbox property tag:0x%08x in_sz:%u out_sz:%zu"
|
||||
|
||||
# mac_via.c
|
||||
via1_rtc_update_data_out(int count, int value) "count=%d value=0x%02x"
|
||||
via1_rtc_update_data_in(int count, int value) "count=%d value=0x%02x"
|
||||
via1_rtc_internal_status(int cmd, int alt, int value) "cmd=0x%02x alt=0x%02x value=0x%02x"
|
||||
via1_rtc_internal_cmd(int cmd) "cmd=0x%02x"
|
||||
via1_rtc_cmd_invalid(int value) "value=0x%02x"
|
||||
via1_rtc_internal_time(uint32_t time) "time=0x%08x"
|
||||
via1_rtc_internal_set_cmd(int cmd) "cmd=0x%02x"
|
||||
via1_rtc_internal_ignore_cmd(int cmd) "cmd=0x%02x"
|
||||
via1_rtc_internal_set_alt(int alt, int sector, int offset) "alt=0x%02x sector=%u offset=%u"
|
||||
via1_rtc_cmd_seconds_read(int reg, int value) "reg=%d value=0x%02x"
|
||||
via1_rtc_cmd_seconds_write(int reg, int value) "reg=%d value=0x%02x"
|
||||
via1_rtc_cmd_test_write(int value) "value=0x%02x"
|
||||
via1_rtc_cmd_wprotect_write(int value) "value=0x%02x"
|
||||
via1_rtc_cmd_pram_read(int addr, int value) "addr=%u value=0x%02x"
|
||||
via1_rtc_cmd_pram_write(int addr, int value) "addr=%u value=0x%02x"
|
||||
via1_rtc_cmd_pram_sect_read(int sector, int offset, int addr, int value) "sector=%u offset=%u addr=%d value=0x%02x"
|
||||
via1_rtc_cmd_pram_sect_write(int sector, int offset, int addr, int value) "sector=%u offset=%u addr=%d value=0x%02x"
|
||||
|
@ -81,6 +81,8 @@ typedef struct MOS6522Q800VIA2State {
|
||||
typedef struct MacVIAState {
|
||||
SysBusDevice busdev;
|
||||
|
||||
VMChangeStateEntry *vmstate;
|
||||
|
||||
/* MMIO */
|
||||
MemoryRegion mmio;
|
||||
MemoryRegion via1mem;
|
||||
@ -100,6 +102,7 @@ typedef struct MacVIAState {
|
||||
uint8_t cmd;
|
||||
int wprotect;
|
||||
int alt;
|
||||
BlockBackend *blk;
|
||||
|
||||
/* ADB */
|
||||
ADBBusState adb_bus;
|
||||
|
@ -114,11 +114,9 @@ static void m68000_cpu_initfn(Object *obj)
|
||||
m68k_set_feature(env, M68K_FEATURE_MOVEP);
|
||||
}
|
||||
|
||||
static void m68020_cpu_initfn(Object *obj)
|
||||
/* common features for 68020, 68030 and 68040 */
|
||||
static void m680x0_cpu_common(CPUM68KState *env)
|
||||
{
|
||||
M68kCPU *cpu = M68K_CPU(obj);
|
||||
CPUM68KState *env = &cpu->env;
|
||||
|
||||
m68k_set_feature(env, M68K_FEATURE_M68000);
|
||||
m68k_set_feature(env, M68K_FEATURE_USP);
|
||||
m68k_set_feature(env, M68K_FEATURE_WORD_INDEX);
|
||||
@ -136,14 +134,31 @@ static void m68020_cpu_initfn(Object *obj)
|
||||
m68k_set_feature(env, M68K_FEATURE_CHK2);
|
||||
m68k_set_feature(env, M68K_FEATURE_MOVEP);
|
||||
}
|
||||
#define m68030_cpu_initfn m68020_cpu_initfn
|
||||
|
||||
static void m68020_cpu_initfn(Object *obj)
|
||||
{
|
||||
M68kCPU *cpu = M68K_CPU(obj);
|
||||
CPUM68KState *env = &cpu->env;
|
||||
|
||||
m680x0_cpu_common(env);
|
||||
m68k_set_feature(env, M68K_FEATURE_M68020);
|
||||
}
|
||||
|
||||
static void m68030_cpu_initfn(Object *obj)
|
||||
{
|
||||
M68kCPU *cpu = M68K_CPU(obj);
|
||||
CPUM68KState *env = &cpu->env;
|
||||
|
||||
m680x0_cpu_common(env);
|
||||
m68k_set_feature(env, M68K_FEATURE_M68030);
|
||||
}
|
||||
|
||||
static void m68040_cpu_initfn(Object *obj)
|
||||
{
|
||||
M68kCPU *cpu = M68K_CPU(obj);
|
||||
CPUM68KState *env = &cpu->env;
|
||||
|
||||
m68020_cpu_initfn(obj);
|
||||
m680x0_cpu_common(env);
|
||||
m68k_set_feature(env, M68K_FEATURE_M68040);
|
||||
}
|
||||
|
||||
@ -166,6 +181,7 @@ static void m68060_cpu_initfn(Object *obj)
|
||||
m68k_set_feature(env, M68K_FEATURE_BKPT);
|
||||
m68k_set_feature(env, M68K_FEATURE_RTD);
|
||||
m68k_set_feature(env, M68K_FEATURE_CHK2);
|
||||
m68k_set_feature(env, M68K_FEATURE_M68060);
|
||||
}
|
||||
|
||||
static void m5208_cpu_initfn(Object *obj)
|
||||
|
@ -460,6 +460,10 @@ void do_m68k_semihosting(CPUM68KState *env, int nr);
|
||||
|
||||
enum m68k_features {
|
||||
M68K_FEATURE_M68000,
|
||||
M68K_FEATURE_M68020,
|
||||
M68K_FEATURE_M68030,
|
||||
M68K_FEATURE_M68040,
|
||||
M68K_FEATURE_M68060,
|
||||
M68K_FEATURE_CF_ISA_A,
|
||||
M68K_FEATURE_CF_ISA_B, /* (ISA B or C). */
|
||||
M68K_FEATURE_CF_ISA_APLUSC, /* BIT/BITREV, FF1, STRLDSR (ISA A+ or C). */
|
||||
@ -481,7 +485,6 @@ enum m68k_features {
|
||||
M68K_FEATURE_BKPT,
|
||||
M68K_FEATURE_RTD,
|
||||
M68K_FEATURE_CHK2,
|
||||
M68K_FEATURE_M68040, /* instructions specific to MC68040 */
|
||||
M68K_FEATURE_MOVEP,
|
||||
};
|
||||
|
||||
|
@ -203,9 +203,17 @@ void HELPER(m68k_movec_to)(CPUM68KState *env, uint32_t reg, uint32_t val)
|
||||
case M68K_CR_VBR:
|
||||
env->vbr = val;
|
||||
return;
|
||||
/* MC680[234]0 */
|
||||
/* MC680[2346]0 */
|
||||
case M68K_CR_CACR:
|
||||
env->cacr = val;
|
||||
if (m68k_feature(env, M68K_FEATURE_M68020)) {
|
||||
env->cacr = val & 0x0000000f;
|
||||
} else if (m68k_feature(env, M68K_FEATURE_M68030)) {
|
||||
env->cacr = val & 0x00003f1f;
|
||||
} else if (m68k_feature(env, M68K_FEATURE_M68040)) {
|
||||
env->cacr = val & 0x80008000;
|
||||
} else if (m68k_feature(env, M68K_FEATURE_M68060)) {
|
||||
env->cacr = val & 0xf8e0e000;
|
||||
}
|
||||
m68k_switch_sp(env);
|
||||
return;
|
||||
/* MC680[34]0 */
|
||||
|
Loading…
Reference in New Issue
Block a user