mac_via: move ADB variables to MOS6522Q800VIA1State

The ADB is accessed using clock and data pins on q800 VIA1 port B and so can be
moved to MOS6522Q800VIA1State.

Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20210830102447.10806-6-mark.cave-ayland@ilande.co.uk>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
This commit is contained in:
Mark Cave-Ayland 2021-08-30 11:24:40 +01:00 committed by Laurent Vivier
parent 741258b06c
commit 5f083d4224
3 changed files with 96 additions and 99 deletions

View File

@ -225,7 +225,7 @@ static void q800_init(MachineState *machine)
hwaddr parameters_base;
CPUState *cs;
DeviceState *dev;
DeviceState *via_dev;
DeviceState *via_dev, *via1_dev;
DeviceState *escc_orgate;
SysBusESPState *sysbus_esp;
ESPState *esp;
@ -285,8 +285,8 @@ static void q800_init(MachineState *machine)
qdev_connect_gpio_out_named(DEVICE(sysbus), "irq", 1,
qdev_get_gpio_in(glue, 1));
adb_bus = qdev_get_child_bus(via_dev, "adb.0");
via1_dev = DEVICE(MOS6522_Q800_VIA1(&MAC_VIA(via_dev)->mos6522_via1));
adb_bus = qdev_get_child_bus(DEVICE(via1_dev), "adb.0");
dev = qdev_new(TYPE_ADB_KEYBOARD);
qdev_realize_and_unref(dev, adb_bus, &error_fatal);
dev = qdev_new(TYPE_ADB_MOUSE);

View File

@ -595,10 +595,9 @@ static void via1_rtc_update(MOS6522Q800VIA1State *v1s)
static void adb_via_poll(void *opaque)
{
MacVIAState *m = opaque;
MOS6522Q800VIA1State *v1s = MOS6522_Q800_VIA1(&m->mos6522_via1);
MOS6522Q800VIA1State *v1s = MOS6522_Q800_VIA1(opaque);
MOS6522State *s = MOS6522(v1s);
ADBBusState *adb_bus = &m->adb_bus;
ADBBusState *adb_bus = &v1s->adb_bus;
uint8_t obuf[9];
uint8_t *data = &s->sr;
int olen;
@ -610,50 +609,50 @@ static void adb_via_poll(void *opaque)
*/
adb_autopoll_block(adb_bus);
if (m->adb_data_in_size > 0 && m->adb_data_in_index == 0) {
if (v1s->adb_data_in_size > 0 && v1s->adb_data_in_index == 0) {
/*
* For older Linux kernels that switch to IDLE mode after sending the
* ADB command, detect if there is an existing response and return that
* as a a "fake" autopoll reply or bus timeout accordingly
*/
*data = m->adb_data_out[0];
olen = m->adb_data_in_size;
*data = v1s->adb_data_out[0];
olen = v1s->adb_data_in_size;
s->b &= ~VIA1B_vADBInt;
qemu_irq_raise(m->adb_data_ready);
qemu_irq_raise(v1s->adb_data_ready);
} else {
/*
* Otherwise poll as normal
*/
m->adb_data_in_index = 0;
m->adb_data_out_index = 0;
v1s->adb_data_in_index = 0;
v1s->adb_data_out_index = 0;
olen = adb_poll(adb_bus, obuf, adb_bus->autopoll_mask);
if (olen > 0) {
/* Autopoll response */
*data = obuf[0];
olen--;
memcpy(m->adb_data_in, &obuf[1], olen);
m->adb_data_in_size = olen;
memcpy(v1s->adb_data_in, &obuf[1], olen);
v1s->adb_data_in_size = olen;
s->b &= ~VIA1B_vADBInt;
qemu_irq_raise(m->adb_data_ready);
qemu_irq_raise(v1s->adb_data_ready);
} else {
*data = m->adb_autopoll_cmd;
*data = v1s->adb_autopoll_cmd;
obuf[0] = 0xff;
obuf[1] = 0xff;
olen = 2;
memcpy(m->adb_data_in, obuf, olen);
m->adb_data_in_size = olen;
memcpy(v1s->adb_data_in, obuf, olen);
v1s->adb_data_in_size = olen;
s->b &= ~VIA1B_vADBInt;
qemu_irq_raise(m->adb_data_ready);
qemu_irq_raise(v1s->adb_data_ready);
}
}
trace_via1_adb_poll(*data, (s->b & VIA1B_vADBInt) ? "+" : "-",
adb_bus->status, m->adb_data_in_index, olen);
adb_bus->status, v1s->adb_data_in_index, olen);
}
static int adb_via_send_len(uint8_t data)
@ -686,11 +685,10 @@ static int adb_via_send_len(uint8_t data)
}
}
static void adb_via_send(MacVIAState *s, int state, uint8_t data)
static void adb_via_send(MOS6522Q800VIA1State *v1s, int state, uint8_t data)
{
MOS6522Q800VIA1State *v1s = MOS6522_Q800_VIA1(&s->mos6522_via1);
MOS6522State *ms = MOS6522(v1s);
ADBBusState *adb_bus = &s->adb_bus;
ADBBusState *adb_bus = &v1s->adb_bus;
uint16_t autopoll_mask;
switch (state) {
@ -706,22 +704,22 @@ static void adb_via_send(MacVIAState *s, int state, uint8_t data)
ms->b &= ~VIA1B_vADBInt;
} else {
ms->b |= VIA1B_vADBInt;
s->adb_data_out_index = 0;
s->adb_data_out[s->adb_data_out_index++] = data;
v1s->adb_data_out_index = 0;
v1s->adb_data_out[v1s->adb_data_out_index++] = data;
}
trace_via1_adb_send(" NEW", data, (ms->b & VIA1B_vADBInt) ? "+" : "-");
qemu_irq_raise(s->adb_data_ready);
qemu_irq_raise(v1s->adb_data_ready);
break;
case ADB_STATE_EVEN:
case ADB_STATE_ODD:
ms->b |= VIA1B_vADBInt;
s->adb_data_out[s->adb_data_out_index++] = data;
v1s->adb_data_out[v1s->adb_data_out_index++] = data;
trace_via1_adb_send(state == ADB_STATE_EVEN ? "EVEN" : " ODD",
data, (ms->b & VIA1B_vADBInt) ? "+" : "-");
qemu_irq_raise(s->adb_data_ready);
qemu_irq_raise(v1s->adb_data_ready);
break;
case ADB_STATE_IDLE:
@ -729,40 +727,39 @@ static void adb_via_send(MacVIAState *s, int state, uint8_t data)
}
/* If the command is complete, execute it */
if (s->adb_data_out_index == adb_via_send_len(s->adb_data_out[0])) {
s->adb_data_in_size = adb_request(adb_bus, s->adb_data_in,
s->adb_data_out,
s->adb_data_out_index);
s->adb_data_in_index = 0;
if (v1s->adb_data_out_index == adb_via_send_len(v1s->adb_data_out[0])) {
v1s->adb_data_in_size = adb_request(adb_bus, v1s->adb_data_in,
v1s->adb_data_out,
v1s->adb_data_out_index);
v1s->adb_data_in_index = 0;
if (adb_bus->status & ADB_STATUS_BUSTIMEOUT) {
/*
* Bus timeout (but allow first EVEN and ODD byte to indicate
* timeout via vADBInt and SRQ status)
*/
s->adb_data_in[0] = 0xff;
s->adb_data_in[1] = 0xff;
s->adb_data_in_size = 2;
v1s->adb_data_in[0] = 0xff;
v1s->adb_data_in[1] = 0xff;
v1s->adb_data_in_size = 2;
}
/*
* If last command is TALK, store it for use by autopoll and adjust
* the autopoll mask accordingly
*/
if ((s->adb_data_out[0] & 0xc) == 0xc) {
s->adb_autopoll_cmd = s->adb_data_out[0];
if ((v1s->adb_data_out[0] & 0xc) == 0xc) {
v1s->adb_autopoll_cmd = v1s->adb_data_out[0];
autopoll_mask = 1 << (s->adb_autopoll_cmd >> 4);
autopoll_mask = 1 << (v1s->adb_autopoll_cmd >> 4);
adb_set_autopoll_mask(adb_bus, autopoll_mask);
}
}
}
static void adb_via_receive(MacVIAState *s, int state, uint8_t *data)
static void adb_via_receive(MOS6522Q800VIA1State *v1s, int state, uint8_t *data)
{
MOS6522Q800VIA1State *v1s = MOS6522_Q800_VIA1(&s->mos6522_via1);
MOS6522State *ms = MOS6522(v1s);
ADBBusState *adb_bus = &s->adb_bus;
ADBBusState *adb_bus = &v1s->adb_bus;
uint16_t pending;
switch (state) {
@ -776,16 +773,16 @@ static void adb_via_receive(MacVIAState *s, int state, uint8_t *data)
trace_via1_adb_receive("IDLE", *data,
(ms->b & VIA1B_vADBInt) ? "+" : "-", adb_bus->status,
s->adb_data_in_index, s->adb_data_in_size);
v1s->adb_data_in_index, v1s->adb_data_in_size);
break;
case ADB_STATE_EVEN:
case ADB_STATE_ODD:
switch (s->adb_data_in_index) {
switch (v1s->adb_data_in_index) {
case 0:
/* First EVEN byte: vADBInt indicates bus timeout */
*data = s->adb_data_in[s->adb_data_in_index];
*data = v1s->adb_data_in[v1s->adb_data_in_index];
if (adb_bus->status & ADB_STATUS_BUSTIMEOUT) {
ms->b &= ~VIA1B_vADBInt;
} else {
@ -794,16 +791,16 @@ static void adb_via_receive(MacVIAState *s, int state, uint8_t *data)
trace_via1_adb_receive(state == ADB_STATE_EVEN ? "EVEN" : " ODD",
*data, (ms->b & VIA1B_vADBInt) ? "+" : "-",
adb_bus->status, s->adb_data_in_index,
s->adb_data_in_size);
adb_bus->status, v1s->adb_data_in_index,
v1s->adb_data_in_size);
s->adb_data_in_index++;
v1s->adb_data_in_index++;
break;
case 1:
/* First ODD byte: vADBInt indicates SRQ */
*data = s->adb_data_in[s->adb_data_in_index];
pending = adb_bus->pending & ~(1 << (s->adb_autopoll_cmd >> 4));
*data = v1s->adb_data_in[v1s->adb_data_in_index];
pending = adb_bus->pending & ~(1 << (v1s->adb_autopoll_cmd >> 4));
if (pending) {
ms->b &= ~VIA1B_vADBInt;
} else {
@ -812,10 +809,10 @@ static void adb_via_receive(MacVIAState *s, int state, uint8_t *data)
trace_via1_adb_receive(state == ADB_STATE_EVEN ? "EVEN" : " ODD",
*data, (ms->b & VIA1B_vADBInt) ? "+" : "-",
adb_bus->status, s->adb_data_in_index,
s->adb_data_in_size);
adb_bus->status, v1s->adb_data_in_index,
v1s->adb_data_in_size);
s->adb_data_in_index++;
v1s->adb_data_in_index++;
break;
default:
@ -825,11 +822,11 @@ static void adb_via_receive(MacVIAState *s, int state, uint8_t *data)
* end of the poll reply, so provide these extra bytes below to
* keep it happy
*/
if (s->adb_data_in_index < s->adb_data_in_size) {
if (v1s->adb_data_in_index < v1s->adb_data_in_size) {
/* Next data byte */
*data = s->adb_data_in[s->adb_data_in_index];
*data = v1s->adb_data_in[v1s->adb_data_in_index];
ms->b |= VIA1B_vADBInt;
} else if (s->adb_data_in_index == s->adb_data_in_size) {
} else if (v1s->adb_data_in_index == v1s->adb_data_in_size) {
if (adb_bus->status & ADB_STATUS_BUSTIMEOUT) {
/* Bus timeout (no more data) */
*data = 0xff;
@ -848,23 +845,22 @@ static void adb_via_receive(MacVIAState *s, int state, uint8_t *data)
trace_via1_adb_receive(state == ADB_STATE_EVEN ? "EVEN" : " ODD",
*data, (ms->b & VIA1B_vADBInt) ? "+" : "-",
adb_bus->status, s->adb_data_in_index,
s->adb_data_in_size);
adb_bus->status, v1s->adb_data_in_index,
v1s->adb_data_in_size);
if (s->adb_data_in_index <= s->adb_data_in_size) {
s->adb_data_in_index++;
if (v1s->adb_data_in_index <= v1s->adb_data_in_size) {
v1s->adb_data_in_index++;
}
break;
}
qemu_irq_raise(s->adb_data_ready);
qemu_irq_raise(v1s->adb_data_ready);
break;
}
}
static void via1_adb_update(MacVIAState *m)
static void via1_adb_update(MOS6522Q800VIA1State *v1s)
{
MOS6522Q800VIA1State *v1s = MOS6522_Q800_VIA1(&m->mos6522_via1);
MOS6522State *s = MOS6522(v1s);
int oldstate, state;
@ -874,10 +870,10 @@ static void via1_adb_update(MacVIAState *m)
if (state != oldstate) {
if (s->acr & VIA1ACR_vShiftOut) {
/* output mode */
adb_via_send(m, state, s->sr);
adb_via_send(v1s, state, s->sr);
} else {
/* input mode */
adb_via_receive(m, state, &s->sr);
adb_via_receive(v1s, state, &s->sr);
}
}
}
@ -895,7 +891,6 @@ static void mos6522_q800_via1_write(void *opaque, hwaddr addr, uint64_t val,
unsigned size)
{
MOS6522Q800VIA1State *v1s = MOS6522_Q800_VIA1(opaque);
MacVIAState *m = container_of(v1s, MacVIAState, mos6522_via1);
MOS6522State *ms = MOS6522(v1s);
addr = (addr >> 9) & 0xf;
@ -904,7 +899,7 @@ static void mos6522_q800_via1_write(void *opaque, hwaddr addr, uint64_t val,
switch (addr) {
case VIA_REG_B:
via1_rtc_update(v1s);
via1_adb_update(m);
via1_adb_update(v1s);
v1s->last_b = ms->b;
break;
@ -954,7 +949,7 @@ static void mac_via_reset(DeviceState *dev)
{
MacVIAState *m = MAC_VIA(dev);
MOS6522Q800VIA1State *v1s = &m->mos6522_via1;
ADBBusState *adb_bus = &m->adb_bus;
ADBBusState *adb_bus = &v1s->adb_bus;
adb_set_autopoll_enabled(adb_bus, true);
@ -967,17 +962,10 @@ static void mac_via_realize(DeviceState *dev, Error **errp)
MacVIAState *m = MAC_VIA(dev);
MOS6522Q800VIA1State *v1s = &m->mos6522_via1;
MOS6522State *ms;
ADBBusState *adb_bus = &m->adb_bus;
ADBBusState *adb_bus = &v1s->adb_bus;
struct tm tm;
int ret;
/* Init VIAs 1 and 2 */
object_initialize_child(OBJECT(dev), "via1", &m->mos6522_via1,
TYPE_MOS6522_Q800_VIA1);
object_initialize_child(OBJECT(dev), "via2", &m->mos6522_via2,
TYPE_MOS6522_Q800_VIA2);
/* Pass through mos6522 output IRQs */
ms = MOS6522(&m->mos6522_via1);
object_property_add_alias(OBJECT(dev), "irq[0]", OBJECT(ms),
@ -1006,9 +994,9 @@ static void mac_via_realize(DeviceState *dev, Error **errp)
qemu_get_timedate(&tm, 0);
v1s->tick_offset = (uint32_t)mktimegm(&tm) + RTC_OFFSET;
adb_register_autopoll_callback(adb_bus, adb_via_poll, m);
m->adb_data_ready = qdev_get_gpio_in_named(dev, "via1-irq",
VIA1_IRQ_ADB_READY_BIT);
adb_register_autopoll_callback(adb_bus, adb_via_poll, v1s);
v1s->adb_data_ready = qdev_get_gpio_in_named(dev, "via1-irq",
VIA1_IRQ_ADB_READY_BIT);
if (v1s->blk) {
int64_t len = blk_getlength(v1s->blk);
@ -1049,9 +1037,12 @@ static void mac_via_init(Object *obj)
&m->mos6522_via2, "via2", VIA_SIZE);
memory_region_add_subregion(&m->mmio, VIA_SIZE, &m->via2mem);
/* ADB */
qbus_create_inplace((BusState *)&m->adb_bus, sizeof(m->adb_bus),
TYPE_ADB_BUS, DEVICE(obj), "adb.0");
/* Init VIAs 1 and 2 */
object_initialize_child(obj, "via1", &m->mos6522_via1,
TYPE_MOS6522_Q800_VIA1);
object_initialize_child(obj, "via2", &m->mos6522_via2,
TYPE_MOS6522_Q800_VIA2);
}
static void via1_postload_update_cb(void *opaque, bool running, RunState state)
@ -1086,13 +1077,6 @@ static const VMStateDescription vmstate_mac_via = {
VMSTATE_INT64(mos6522_via1.next_second, MacVIAState),
VMSTATE_TIMER_PTR(mos6522_via1.sixty_hz_timer, MacVIAState),
VMSTATE_INT64(mos6522_via1.next_sixty_hz, MacVIAState),
/* ADB */
VMSTATE_INT32(adb_data_in_size, MacVIAState),
VMSTATE_INT32(adb_data_in_index, MacVIAState),
VMSTATE_INT32(adb_data_out_index, MacVIAState),
VMSTATE_BUFFER(adb_data_in, MacVIAState),
VMSTATE_BUFFER(adb_data_out, MacVIAState),
VMSTATE_UINT8(adb_autopoll_cmd, MacVIAState),
VMSTATE_END_OF_LIST()
}
};
@ -1130,6 +1114,12 @@ static void mos6522_q800_via1_reset(DeviceState *dev)
static void mos6522_q800_via1_init(Object *obj)
{
MOS6522Q800VIA1State *v1s = MOS6522_Q800_VIA1(obj);
/* ADB */
qbus_create_inplace((BusState *)&v1s->adb_bus, sizeof(v1s->adb_bus),
TYPE_ADB_BUS, DEVICE(v1s), "adb.0");
qdev_init_gpio_in_named(DEVICE(obj), via1_irq_request, "via1-irq",
VIA1_IRQ_NB);
}
@ -1153,6 +1143,13 @@ static const VMStateDescription vmstate_q800_via1 = {
VMSTATE_UINT8(cmd, MOS6522Q800VIA1State),
VMSTATE_INT32(wprotect, MOS6522Q800VIA1State),
VMSTATE_INT32(alt, MOS6522Q800VIA1State),
/* ADB */
VMSTATE_INT32(adb_data_in_size, MOS6522Q800VIA1State),
VMSTATE_INT32(adb_data_in_index, MOS6522Q800VIA1State),
VMSTATE_INT32(adb_data_out_index, MOS6522Q800VIA1State),
VMSTATE_BUFFER(adb_data_in, MOS6522Q800VIA1State),
VMSTATE_BUFFER(adb_data_out, MOS6522Q800VIA1State),
VMSTATE_UINT8(adb_autopoll_cmd, MOS6522Q800VIA1State),
VMSTATE_END_OF_LIST()
}
};

View File

@ -56,6 +56,16 @@ struct MOS6522Q800VIA1State {
int wprotect;
int alt;
/* ADB */
ADBBusState adb_bus;
qemu_irq adb_data_ready;
int adb_data_in_size;
int adb_data_in_index;
int adb_data_out_index;
uint8_t adb_data_in[128];
uint8_t adb_data_out[16];
uint8_t adb_autopoll_cmd;
/* external timers */
QEMUTimer *one_second_timer;
int64_t next_second;
@ -102,16 +112,6 @@ struct MacVIAState {
/* VIAs */
MOS6522Q800VIA1State mos6522_via1;
MOS6522Q800VIA2State mos6522_via2;
/* ADB */
ADBBusState adb_bus;
qemu_irq adb_data_ready;
int adb_data_in_size;
int adb_data_in_index;
int adb_data_out_index;
uint8_t adb_data_in[128];
uint8_t adb_data_out[16];
uint8_t adb_autopoll_cmd;
};
#endif