aboutsummaryrefslogtreecommitdiff
path: root/hw/misc/mac_via.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/misc/mac_via.c')
-rw-r--r--hw/misc/mac_via.c87
1 files changed, 37 insertions, 50 deletions
diff --git a/hw/misc/mac_via.c b/hw/misc/mac_via.c
index 71b74c3372..525e38ce93 100644
--- a/hw/misc/mac_via.c
+++ b/hw/misc/mac_via.c
@@ -325,10 +325,11 @@ static void via1_sixty_hz(void *opaque)
{
MOS6522Q800VIA1State *v1s = opaque;
MOS6522State *s = MOS6522(v1s);
- MOS6522DeviceClass *mdc = MOS6522_GET_CLASS(s);
+ qemu_irq irq = qdev_get_gpio_in(DEVICE(s), VIA1_IRQ_60HZ_BIT);
- s->ifr |= VIA1_IRQ_60HZ;
- mdc->update_irq(s);
+ /* Negative edge trigger */
+ qemu_irq_lower(irq);
+ qemu_irq_raise(irq);
via1_sixty_hz_update(v1s);
}
@@ -337,44 +338,15 @@ static void via1_one_second(void *opaque)
{
MOS6522Q800VIA1State *v1s = opaque;
MOS6522State *s = MOS6522(v1s);
- MOS6522DeviceClass *mdc = MOS6522_GET_CLASS(s);
+ qemu_irq irq = qdev_get_gpio_in(DEVICE(s), VIA1_IRQ_ONE_SECOND_BIT);
- s->ifr |= VIA1_IRQ_ONE_SECOND;
- mdc->update_irq(s);
+ /* Negative edge trigger */
+ qemu_irq_lower(irq);
+ qemu_irq_raise(irq);
via1_one_second_update(v1s);
}
-static void via1_irq_request(void *opaque, int irq, int level)
-{
- MOS6522Q800VIA1State *v1s = opaque;
- MOS6522State *s = MOS6522(v1s);
- MOS6522DeviceClass *mdc = MOS6522_GET_CLASS(s);
-
- if (level) {
- s->ifr |= 1 << irq;
- } else {
- s->ifr &= ~(1 << irq);
- }
-
- mdc->update_irq(s);
-}
-
-static void via2_irq_request(void *opaque, int irq, int level)
-{
- MOS6522Q800VIA2State *v2s = opaque;
- MOS6522State *s = MOS6522(v2s);
- MOS6522DeviceClass *mdc = MOS6522_GET_CLASS(s);
-
- if (level) {
- s->ifr |= 1 << irq;
- } else {
- s->ifr &= ~(1 << irq);
- }
-
- mdc->update_irq(s);
-}
-
static void pram_update(MOS6522Q800VIA1State *v1s)
{
@@ -938,9 +910,26 @@ static uint64_t mos6522_q800_via2_read(void *opaque, hwaddr addr, unsigned size)
{
MOS6522Q800VIA2State *s = MOS6522_Q800_VIA2(opaque);
MOS6522State *ms = MOS6522(s);
+ uint64_t val;
addr = (addr >> 9) & 0xf;
- return mos6522_read(ms, addr, size);
+ val = mos6522_read(ms, addr, size);
+
+ switch (addr) {
+ case VIA_REG_IFR:
+ /*
+ * On a Q800 an emulated VIA2 is integrated into the onboard logic. The
+ * expectation of most OSs is that the DRQ bit is live, rather than
+ * latched as it would be on a real VIA so do the same here.
+ *
+ * Note: DRQ is negative edge triggered
+ */
+ val &= ~VIA2_IRQ_SCSI_DATA;
+ val |= (~ms->last_irq_levels & VIA2_IRQ_SCSI_DATA);
+ break;
+ }
+
+ return val;
}
static void mos6522_q800_via2_write(void *opaque, hwaddr addr, uint64_t val,
@@ -1061,8 +1050,6 @@ static void mos6522_q800_via1_init(Object *obj)
qbus_init((BusState *)&v1s->adb_bus, sizeof(v1s->adb_bus),
TYPE_ADB_BUS, DEVICE(v1s), "adb.0");
- qdev_init_gpio_in(DEVICE(obj), via1_irq_request, VIA1_IRQ_NB);
-
/* A/UX mode */
qdev_init_gpio_out(DEVICE(obj), &v1s->auxmode_irq, 1);
}
@@ -1110,9 +1097,11 @@ static Property mos6522_q800_via1_properties[] = {
static void mos6522_q800_via1_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
+ MOS6522DeviceClass *mdc = MOS6522_CLASS(oc);
dc->realize = mos6522_q800_via1_realize;
- dc->reset = mos6522_q800_via1_reset;
+ device_class_set_parent_reset(dc, mos6522_q800_via1_reset,
+ &mdc->parent_reset);
dc->vmsd = &vmstate_q800_via1;
device_class_set_props(dc, mos6522_q800_via1_properties);
}
@@ -1150,22 +1139,21 @@ static void mos6522_q800_via2_reset(DeviceState *dev)
ms->a = 0x7f;
}
-static void via2_nubus_irq_request(void *opaque, int irq, int level)
+static void via2_nubus_irq_request(void *opaque, int n, int level)
{
MOS6522Q800VIA2State *v2s = opaque;
MOS6522State *s = MOS6522(v2s);
- MOS6522DeviceClass *mdc = MOS6522_GET_CLASS(s);
+ qemu_irq irq = qdev_get_gpio_in(DEVICE(s), VIA2_IRQ_NUBUS_BIT);
if (level) {
/* Port A nubus IRQ inputs are active LOW */
- s->a &= ~(1 << irq);
- s->ifr |= 1 << VIA2_IRQ_NUBUS_BIT;
+ s->a &= ~(1 << n);
} else {
- s->a |= (1 << irq);
- s->ifr &= ~(1 << VIA2_IRQ_NUBUS_BIT);
+ s->a |= (1 << n);
}
- mdc->update_irq(s);
+ /* Negative edge trigger */
+ qemu_set_irq(irq, !level);
}
static void mos6522_q800_via2_init(Object *obj)
@@ -1177,8 +1165,6 @@ static void mos6522_q800_via2_init(Object *obj)
"via2", VIA_SIZE);
sysbus_init_mmio(sbd, &v2s->via_mem);
- qdev_init_gpio_in(DEVICE(obj), via2_irq_request, VIA2_IRQ_NB);
-
qdev_init_gpio_in_named(DEVICE(obj), via2_nubus_irq_request, "nubus-irq",
VIA2_NUBUS_IRQ_NB);
}
@@ -1199,7 +1185,8 @@ static void mos6522_q800_via2_class_init(ObjectClass *oc, void *data)
DeviceClass *dc = DEVICE_CLASS(oc);
MOS6522DeviceClass *mdc = MOS6522_CLASS(oc);
- dc->reset = mos6522_q800_via2_reset;
+ device_class_set_parent_reset(dc, mos6522_q800_via2_reset,
+ &mdc->parent_reset);
dc->vmsd = &vmstate_q800_via2;
mdc->portB_write = mos6522_q800_via2_portB_write;
}